import re
from pathlib import Path
from tarina.lang import lang
from tarina.lang.schema import _TemplateDict, get_template
import keyword


class LangItem:
    def __init__(self, scope: str, type: str):
        self.scope = scope
        self.type = type

    def __call__(self, **format_kwargs):
        return lang.require(self.scope, self.type).format(**format_kwargs)

    def __iter__(self):
        return iter([self.scope, self.type])

class LangModel:
    pass


MODEL_TEMPLATE = """\
# This file is @generated by tarina.lang CLI tool
# It is not intended for manual editing.

from tarina.lang.model import LangModel, LangItem


{scope_classes}
class Lang(LangModel):
{scopes}
"""


SCOPE_TEMPLATE = """\
class {scope}:
{types}
"""

TYPE_TEMPLATE = """\
    {name}: LangItem = LangItem("{scope}", "{type}")
"""



def generate_model(root: Path):
    template = get_template(root)
    if "scopes" not in template:
        raise KeyError("Template file must have a 'scopes' key")
    scopes: list[_TemplateDict] = template["scopes"]
    scopes_classes = ""
    scopes_str = ""
    for s in scopes:
        scope = re.sub(r"[\W\s]+", "_", s["scope"])
        if scope in keyword.kwlist:
            scope += "_"
        scope_class = scope.capitalize()
        if scope_class == "Lang":
            scope_class += "_"
        types_str = ""
        for t in s["types"]:
            name = re.sub(r"[\W\s]+", "_", t)
            if name in keyword.kwlist:
                name += "_"
            types_str += TYPE_TEMPLATE.format(name=t, scope=s["scope"], type=t)
        scopes_classes += SCOPE_TEMPLATE.format(scope=scope_class, types=types_str)
        scopes_str += f"    {scope} = {scope_class}\n"
    return MODEL_TEMPLATE.format(scope_classes=scopes_classes, scopes=scopes_str)


def write_model(root: Path):
    model = generate_model(root)
    with (root / f"model.py").open("w", encoding="utf-8") as f:
        f.write(model)
