from .meta import print_version
from .lexer import LexerInfo, lexical_analysis
from .interpreter import InterpreterState, StackType


REPL_FILE_NAME = "<STDIN>"


def print_top_of_stack(interpreter: InterpreterState) -> None:
    """Pretty-print top of the stack."""

    item = interpreter.top()
    if item is None:
        print("#0: <STACK IS EMPTY>")
        return

    t = item.type

    if t == StackType.IDENTIFIER:
        print(f"#0: ::{item.value}")
    elif t == StackType.I64:
        print(f"#0: {item.value}")
    elif t in {StackType.I32, StackType.I16, StackType.I8}:
        print(f"#0: {item.value}:{t}")
    elif t in {StackType.U64, StackType.U32, StackType.U16, StackType.U8}:
        print(f"#0: {item.value}:{t}")
    elif t == StackType.FLOAT:
        print(f"#0: {item.value}:f32")
    elif t == StackType.DOUBLE:
        print(f"#0: {item.value}")
    elif t == StackType.CHARACTER:
        print(f"#0: {item.value}")
    elif t == StackType.BOOLEAN:
        print("#0: TRUE" if item.value else "#0: FALSE")
    elif t == StackType.TOKEN_STRING:
        print("#0: <TOKEN STRING>")
    elif t == StackType.CALLABLE:
        print("#0: <CALLABLE>")
    else:
        print(f"#0: <UNKNOWN {t}>")


def repl() -> int:
    """Interactive interpreter loop."""

    print_version()
    print("===== YREA SLS REPL =====")
    print("Type `#exit` to exit.")

    interpreter = InterpreterState()

    while True:
        try:
            line = input("> ")
        except EOFError:
            break

        if line.strip() == "#exit":
            return 0

        # Create a fresh lexer each iteration
        lexer_info = LexerInfo(filename=REPL_FILE_NAME, source_code=line)

        try:
            tokens = lexical_analysis(lexer_info)
        except Exception as err:
            print(err)
            continue

        # Execute tokens in order
        for token in tokens:
            try:
                ok = interpreter.execute(token)
                if not ok:
                    print("A runtime error occurred!")
                    break
            except Exception as err:
                print(err)
                break

        print_top_of_stack(interpreter)

    return 1
