package token;

import static error.ErrorManager.Severity.CRITICAL;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

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() {
        assertTrue(tokenFactory.createEofToken(testPosition) instanceof Eof);
    }

    @Test
    public void leftParenthesisCreation() {
        String text = "(";
        assertTrue(createToken(text) instanceof LeftParenthesis);
    }

    @Test
    public void rightParenthesisCreation() {
        String text = ")";
        assertTrue(createToken(text) instanceof RightParenthesis);
    }

    @Test
    public void quoteMarkCreation() {
        String text = "'";
        assertTrue(createToken(text) instanceof QuoteMark);
    }

    @Test
    public void numberCreation() {
        String text = "987";
        assertTrue(createToken(text) instanceof Number);
    }

    @Test
    public void prefixedNumberCreation() {
        String text = "-987";
        assertTrue(createToken(text) instanceof Number);
    }

    @Test
    public void identifierCreation() {
        String text = "identifier";
        assertTrue(createToken(text) instanceof Identifier);
    }

    @Test
    public void prefixedIdentifierCreation() {
        String text = "-identifier";
        assertTrue(createToken(text) instanceof Identifier);
    }

    @Test
    public void stringCreation() {
        String text = "\"string\"";
        assertTrue(createToken(text) instanceof QuotedString);
    }

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

    @Test
    public void emptyTokenTextException_ContainsCorrectAttributes() {
        try {
            createToken("");
        } catch (EmptyTokenTextException e) {
            String message = e.getMessage();
            assertNotNull(message);
            assertTrue(message.length() > 0);
            assertEquals(CRITICAL, e.getSeverity());
        }
    }

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

    @Test
    public void backTickCreation() {
        String text = "`";
        assertTrue(createToken(text) instanceof Backquote);
    }

    @Test
    public void commaCreation() {
        String text = ",";
        assertTrue(createToken(text) instanceof Comma);
    }

    @Test
    public void atSignCreation() {
        String text = "@";
        assertTrue(createToken(text) instanceof AtSign);
    }

}
