#!/usr/bin/env python3
# ex: set filetype=python:

"""Translate an XDR specification into executable code that
can be compiled for the Linux kernel."""

import logging

from argparse import Namespace
from lark import logger
from lark.exceptions import VisitError

from generators.source_top import XdrSourceTopGenerator
from generators.enum import XdrEnumGenerator
from generators.passthru import XdrPassthruGenerator
from generators.pointer import XdrPointerGenerator
from generators.program import XdrProgramGenerator
from generators.typedef import XdrTypedefGenerator
from generators.struct import XdrStructGenerator
from generators.union import XdrUnionGenerator

from xdr_ast import transform_parse_tree, _RpcProgram, Specification
from xdr_ast import _XdrAst, _XdrEnum, _XdrPassthru, _XdrPointer
from xdr_ast import _XdrStruct, _XdrTypedef, _XdrUnion, XdrSemanticError

from xdr_parse import xdr_parser, set_xdr_annotate, set_xdr_enum_validation
from xdr_parse import make_error_handler, XdrParseError
from xdr_parse import handle_transform_error, handle_semantic_error

logger.setLevel(logging.INFO)


def emit_source_decoder(node: _XdrAst, language: str, peer: str) -> None:
    """Emit one XDR decoder function for a source file"""
    if isinstance(node, _XdrEnum):
        gen = XdrEnumGenerator(language, peer)
    elif isinstance(node, _XdrPointer):
        gen = XdrPointerGenerator(language, peer)
    elif isinstance(node, _XdrTypedef):
        gen = XdrTypedefGenerator(language, peer)
    elif isinstance(node, _XdrStruct):
        gen = XdrStructGenerator(language, peer)
    elif isinstance(node, _XdrUnion):
        gen = XdrUnionGenerator(language, peer)
    elif isinstance(node, _RpcProgram):
        gen = XdrProgramGenerator(language, peer)
    else:
        return
    gen.emit_decoder(node)


def emit_source_encoder(node: _XdrAst, language: str, peer: str) -> None:
    """Emit one XDR encoder function for a source file"""
    if isinstance(node, _XdrEnum):
        gen = XdrEnumGenerator(language, peer)
    elif isinstance(node, _XdrPointer):
        gen = XdrPointerGenerator(language, peer)
    elif isinstance(node, _XdrTypedef):
        gen = XdrTypedefGenerator(language, peer)
    elif isinstance(node, _XdrStruct):
        gen = XdrStructGenerator(language, peer)
    elif isinstance(node, _XdrUnion):
        gen = XdrUnionGenerator(language, peer)
    elif isinstance(node, _RpcProgram):
        gen = XdrProgramGenerator(language, peer)
    else:
        return
    gen.emit_encoder(node)


def generate_server_source(filename: str, root: Specification, language: str) -> None:
    """Generate server-side source code"""

    gen = XdrSourceTopGenerator(language, "server")
    gen.emit_source(filename, root)

    for definition in root.definitions:
        if isinstance(definition.value, _XdrPassthru):
            passthru_gen = XdrPassthruGenerator(language, "server")
            passthru_gen.emit_decoder(definition.value)
        else:
            emit_source_decoder(definition.value, language, "server")
    for definition in root.definitions:
        if not isinstance(definition.value, _XdrPassthru):
            emit_source_encoder(definition.value, language, "server")


def generate_client_source(filename: str, root: Specification, language: str) -> None:
    """Generate client-side source code"""

    gen = XdrSourceTopGenerator(language, "client")
    gen.emit_source(filename, root)

    for definition in root.definitions:
        if isinstance(definition.value, _XdrPassthru):
            passthru_gen = XdrPassthruGenerator(language, "client")
            passthru_gen.emit_decoder(definition.value)
        else:
            emit_source_encoder(definition.value, language, "client")
    for definition in root.definitions:
        if not isinstance(definition.value, _XdrPassthru):
            emit_source_decoder(definition.value, language, "client")

    # cel: todo: client needs PROC macros


def subcmd(args: Namespace) -> int:
    """Generate encoder and decoder functions"""

    set_xdr_annotate(args.annotate)
    set_xdr_enum_validation(not args.no_enum_validation)
    parser = xdr_parser()
    with open(args.filename, encoding="utf-8") as f:
        source = f.read()
        try:
            parse_tree = parser.parse(
                source, on_error=make_error_handler(source, args.filename)
            )
        except XdrParseError:
            return 1
        try:
            ast = transform_parse_tree(parse_tree)
        except VisitError as e:
            handle_transform_error(e, source, args.filename)
            return 1
        except XdrSemanticError as e:
            handle_semantic_error(e, source, args.filename)
            return 1
        match args.peer:
            case "server":
                generate_server_source(args.filename, ast, args.language)
            case "client":
                generate_client_source(args.filename, ast, args.language)
            case _:
                print("Code generation for", args.peer, "is not yet supported")

    return 0
