package p.studio.compiler.pbs;

import p.studio.compiler.pbs.lexer.PbsToken;

import java.util.Arrays;
import java.util.List;

public enum PbsSemanticKind {
    COMMENT("pbs-comment"),
    STRING("pbs-string"),
    NUMBER("pbs-number"),
    LITERAL("pbs-literal"),
    LIFECYCLE("pbs-lifecycle"),
    KEYWORD("pbs-keyword"),
    OPERATOR("pbs-operator"),
    PUNCTUATION("pbs-punctuation"),
    FUNCTION("pbs-function"),
    METHOD("pbs-method"),
    CONSTRUCTOR("pbs-constructor"),
    STRUCT("pbs-struct"),
    CONTRACT("pbs-contract"),
    HOST("pbs-host"),
    BUILTIN_TYPE("pbs-builtin-type"),
    SERVICE("pbs-service"),
    ERROR("pbs-error"),
    ENUM("pbs-enum"),
    CALLBACK("pbs-callback"),
    GLOBAL("pbs-global"),
    CONST("pbs-const"),
    IMPLEMENTS("pbs-implements"),
    IDENTIFIER("pbs-identifier");

    private final String semanticKey;

    PbsSemanticKind(final String semanticKey) {
        this.semanticKey = semanticKey;
    }

    public String semanticKey() {
        return semanticKey;
    }

    public static List<String> semanticKeys() {
        return Arrays.stream(values())
                .map(PbsSemanticKind::semanticKey)
                .toList();
    }

    public static PbsSemanticKind forToken(final PbsToken token) {
        return switch (token.kind()) {
            case COMMENT -> COMMENT;
            case STRING_LITERAL -> STRING;
            case INT_LITERAL, FLOAT_LITERAL, BOUNDED_LITERAL -> NUMBER;
            case TRUE, FALSE, NONE -> LITERAL;
            case IMPORT, FROM, AS, SERVICE, HOST, FN, APPLY, BIND, NEW, IMPLEMENTS, USING, CTOR,
                 DECLARE, LET, CONST, GLOBAL, STRUCT, CONTRACT, ERROR, ENUM, CALLBACK, BUILTIN,
                 SELF, THIS, PUB, MUT, MOD, TYPE, IF, ELSE, SWITCH, DEFAULT, FOR, UNTIL, STEP,
                 WHILE, BREAK, CONTINUE, RETURN, VOID, OPTIONAL, RESULT, SOME, OK, ERR, HANDLE,
                 AND, OR, NOT, SPAWN, YIELD, SLEEP, MATCH -> KEYWORD;
            case PLUS, MINUS, STAR, SLASH, PERCENT, BANG, PLUS_EQUAL, MINUS_EQUAL, STAR_EQUAL,
                 SLASH_EQUAL, PERCENT_EQUAL, BANG_EQUAL, EQUAL, EQUAL_EQUAL, LESS, LESS_EQUAL,
                 GREATER, GREATER_EQUAL, AND_AND, OR_OR, ARROW, QUESTION -> OPERATOR;
            case LEFT_PAREN, RIGHT_PAREN, LEFT_BRACE, RIGHT_BRACE, LEFT_BRACKET, RIGHT_BRACKET,
                 COMMA, COLON, SEMICOLON, AT, DOT, DOT_DOT -> PUNCTUATION;
            case IDENTIFIER, EOF -> null;
        };
    }
}
