package token;

import static java.lang.Character.isDigit;
import static util.Characters.AT_SIGN;
import static util.Characters.BACKQUOTE;
import static util.Characters.COMMA;
import static util.Characters.DOUBLE_QUOTE;
import static util.Characters.LEFT_PARENTHESIS;
import static util.Characters.RIGHT_PARENTHESIS;
import static util.Characters.SINGLE_QUOTE;
import static util.Characters.isLegalIdentifierCharacter;
import static util.Characters.isNumberPrefix;

import file.FilePosition;

public class TokenFactoryImpl implements TokenFactory {

    @Override
    public Token createToken(String text, FilePosition position) {
        if (text.length() == 0)
            throw new EmptyTokenTextException(position);

        char firstCharacter = text.charAt(0);

        switch (firstCharacter) {
        case LEFT_PARENTHESIS:
            return new LeftParenthesis(text, position);
        case RIGHT_PARENTHESIS:
            return new RightParenthesis(text, position);
        case SINGLE_QUOTE:
            return new QuoteMark(text, position);
        case DOUBLE_QUOTE:
            return new QuotedString(text, position);
        case BACKQUOTE:
            return new Backquote(text, position);
        case AT_SIGN:
            return new AtSign(text, position);
        case COMMA:
            return new Comma(text, position);
        default:
            if (isNumeric(firstCharacter, text)) {
                return new Number(text, position);
            } else if (isLegalIdentifierCharacter(firstCharacter)) {
                return new Identifier(text, position);
            }
        }

        throw new BadCharacterException(text, position);
    }

    private boolean isNumeric(char firstCharacter, String text) {
        return isDigit(firstCharacter) || isPrefixedNumeric(firstCharacter, text);
    }

    private boolean isPrefixedNumeric(char firstCharacter, String text) {
        return isNumberPrefix(firstCharacter) && isNextCharacterDigit(text);
    }

    private boolean isNextCharacterDigit(String text) {
        return (text.length() > 1) && isDigit(text.charAt(1));
    }

    @Override
    public Token createEofToken(FilePosition position) {
        return new Eof("EOF", position);
    }

}
