# Copyright (c) 2017-2026 Juancarlo Añez (apalala@gmail.com)
# SPDX-License-Identifier: BSD-4-Clause
from __future__ import annotations

from .. import peg as g
from .._version import __version__ as version
from ..util.common import typename
from ..util.indent import IndentPrintMixin
from .boilerplt import FOOTER
from .ngparser_gen import keywordsgen, textinputgen


def parsermodel_gen(model: g.Grammar, name: str | None = None) -> str:
    model = model.optimized()
    generator = ParseWithModelGenerator()
    return generator.generate_parser(model, name=name)


def PARSER(name: str) -> str:
    return f"""\
    #!/usr/bin/env python3
    #
    #  CAVEAT UTILITOR
    #
    #  This file was automatically generated by 竜TatSu v{version}
    #
    #     https://pypi.python.org/pypi/tatsu/
    #
    #  Any changes you make to it will be overwritten the next time
    #  the file is generated.
    #
    # noqa # type: ignore # ruff: noqa
    # copyright: ignore
    # fmt: off

    from __future__ import annotations
    from typing import Any

    from tatsu.config import ParserConfig
    from tatsu.contexts import CanParse
    from tatsu.input import Text
    from tatsu.input.buffer import Buffer
    from tatsu.input.textlines import TextLines
    from tatsu.peg import *


    class {name}Parser(CanParse):
        def __init__(self, config: Any = None, **settings: Any):
            self.config = ParserConfig.new(config, **settings)
            self.model = GRAMMAR_MODEL

        def parse(
            self,
            text: str | Text,
            /,
            *,
            start: str | None = None,
            asmodel: bool = True,
            config: Any = None,
            **settings: Any,
        ) -> Any:
            # NOTE
            #   Copy the grammar so the configuration is unique to this parse
            #   and one parse doesn't leak settings to another.
            #   There may be also configurations that are unique to this parse.
            model = Grammar(
                name=self.model.name,
                rules=self.model.rules,
                directives=self.model.directives,
                keywords=self.model.keywords,
                config=self.config,
            )
            config = ParserConfig.new(config, **settings)
            return model.parse(text, asmodel=asmodel, config=config)
    """


class ParseWithModelGenerator(IndentPrintMixin):
    def generate_parser(self, grammar: g.Grammar, name: str | None = None) -> str:
        name = name or grammar.name or ''
        self.clear()
        self.print()

        self.print(PARSER(name))
        self.print()
        self.print()

        self.print(f'GRAMMAR_MODEL: {typename(grammar)} = (')
        with self.indent():
            self.print(repr(grammar.optimized()))
        self.print(')')
        self.print()
        self.print()

        self.print(textinputgen(grammar, name))
        self.print()

        self.print(keywordsgen(grammar))
        self.print()

        self.print(FOOTER(name))

        return f"{self.printed_text().strip()}\n"
