package tokens;

/**
 * Ein Token ist ein zusammengehöriges Symbol, das Teil eines mathematischen Ausdrucks ist. Es entspricht ungefähr
 * einem "Wort"; hier kann es entweder Operatoren oder Operanden von Rechenoperationen darstellen. Eine einzelne Zahl
 * (nicht Ziffer) ist bspw. ein Token, die Variable x ist ein Token, ein Operator ist ein Token, der Name einer Funktion
 * ist ein Token.
 */
public class Token {

    protected TokenType type;

    protected Token() {
    }

    /**
     * Erzeugt einen Token mit dem angegebenen Typ.
     * @param type Tokentyp.
     */
    public Token(TokenType type) {
        if (type == TokenType.NUMBER) {
            throw new IllegalArgumentException("NumberToken muss mit NumberToken(number) erzeugt werden");
        } else if (type == TokenType.FUNCTION) {
            throw new IllegalArgumentException("FunctionToken muss mit FunctionToken(name) erzeugt werden");
        }
        this.type = type;
    }

    /**
     * getType gibt den Typ dieses Tokens zurück.
     * @return Tokentyp.
     */
    public TokenType getType() {
        return this.type;
    }

    /**
     * TODO: Schreibe eine Javadoc für diese Methode.
     */
    public int ranking() {
        switch (this.type) {
            case PLUS:
            case MINUS:
                return 1;
            case TIMES:
            case DIVIDED:
                return 2;
            case POWER:
                return 3;
            default:
                return -1;
        }
    }

    /**
     * TODO: Schreibe eine Javadoc für diese Methode.
     */
    public boolean isLeftAssociative() {
        return this.type != TokenType.POWER;
    }

    /**
     * toString gibt den Token in lesbarer Form aus.
     * @return Token als String.
     */
    public String toString() {
        switch (this.type) {
            case X:
                return "x";
            case PLUS:
                return "+";
            case MINUS:
                return "-";
            case TIMES:
                return "*";
            case DIVIDED:
                return "/";
            case POWER:
                return "^";
            case OPENING_PARENTHESIS:
                return "(";
            case CLOSING_PARENTHESIS:
                return ")";
            default:
                throw new IllegalArgumentException("Kein toString für tokenType " + this.type);
        }
    }
}
