package token;

import static error.ErrorManager.Severity.CRITICAL;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Before;
import org.junit.Test;

import file.FilePosition;
import token.TokenFactory.BadCharacterException;
import token.TokenFactory.EmptyTokenTextException;

public class TokenFactoryTest {

    private TokenFactory tokenFactory;
    private FilePosition testPosition;

    @Before
    public void setUp() {
        tokenFactory = new TokenFactoryImpl();
        testPosition = new FilePosition("testFile");
        testPosition.setLineNumber(0);
        testPosition.setColumnNumber(0);
    }

    private Token createToken(String text) {
        return tokenFactory.createToken(text, testPosition);
    }

    @Test
    public void eofTokenCreation() {
        assertThat(tokenFactory.createEofToken(testPosition), instanceOf(Eof.class));
    }

    @Test
    public void leftParenthesisCreation() {
        String text = "(";
        assertThat(createToken(text), instanceOf(LeftParenthesis.class));
    }

    @Test
    public void rightParenthesisCreation() {
        String text = ")";
        assertThat(createToken(text), instanceOf(RightParenthesis.class));
    }

    @Test
    public void quoteMarkCreation() {
        String text = "'";
        assertThat(createToken(text), instanceOf(QuoteMark.class));
    }

    @Test
    public void numberCreation() {
        String text = "987";
        assertThat(createToken(text), instanceOf(Number.class));
    }

    @Test
    public void prefixedNumberCreation() {
        String text = "-987";
        assertThat(createToken(text), instanceOf(Number.class));
    }

    @Test
    public void identifierCreation() {
        String text = "identifier";
        assertThat(createToken(text), instanceOf(Identifier.class));
    }

    @Test
    public void prefixedIdentifierCreation() {
        String text = "-identifier";
        assertThat(createToken(text), instanceOf(Identifier.class));
    }

    @Test
    public void stringCreation() {
        String text = "\"string\"";
        assertThat(createToken(text), instanceOf(QuotedString.class));
    }

    @Test(expected = EmptyTokenTextException.class)
    public void emptyString_ThrowsException() {
        createToken("");
    }

    @Test
    public void emptyTokenTextException_ContainsCorrectAttributes() {
        try {
            createToken("");
        } catch (EmptyTokenTextException e) {
            String message = e.getMessage();
            assertThat(message, is(notNullValue()));
            assertThat(message.length(), greaterThan(0));
            assertThat(e.getSeverity(), is(CRITICAL));
        }
    }

    @Test(expected = BadCharacterException.class)
    public void badCharacter_ThrowsException() {
        createToken("[abc]");
    }

    @Test
    public void backTickCreation() {
        String text = "`";
        assertThat(createToken(text), instanceOf(Backquote.class));
    }

    @Test
    public void commaCreation() {
        String text = ",";
        assertThat(createToken(text), instanceOf(Comma.class));
    }

    @Test
    public void atSignCreation() {
        String text = "@";
        assertThat(createToken(text), instanceOf(AtSign.class));
    }

}
