# SPDX-License-Identifier: Apache-2.0
# Copyright 2021 The Meson development team
from __future__ import annotations

from pathlib import Path
import json
import re

from .generatorbase import GeneratorBase
from . import jsonschema as J
from .model import (
    ReferenceManual,
    Function,
    Object,
    Type,

    PosArg,
    VarArgs,
    Kwarg,
)

import typing as T

class GeneratorJSON(GeneratorBase):
    def __init__(self, manual: ReferenceManual, out: Path, enable_modules: bool) -> None:
        super().__init__(manual)
        self.out = out
        self.enable_modules = enable_modules

    def _generate_type(self, typ: Type) -> T.List[J.Type]:
        return [
            {
                'obj': x.data_type.name,
                'holds': self._generate_type(x.holds) if x.holds else [],
            }
            for x in typ.resolved
        ]

    def _generate_type_str(self, typ: Type) -> str:
        # Remove all whitespaces
        return re.sub(r'[ \n\r\t]', '', typ.raw)

    def _generate_arg(self, arg: T.Union[PosArg, VarArgs, Kwarg], isOptarg: bool = False) -> J.Argument:
        return {
            'name': arg.name,
            'description': arg.description,
            'since': arg.since if arg.since else None,
            'deprecated': arg.deprecated if arg.deprecated else None,
            'type': self._generate_type(arg.type),
            'type_str': self._generate_type_str(arg.type),
            'required': arg.required if isinstance(arg, Kwarg) else not isOptarg and not isinstance(arg, VarArgs),
            'default': arg.default if isinstance(arg, (PosArg, Kwarg)) else None,
            'min_varargs': arg.min_varargs if isinstance(arg, VarArgs) and arg.min_varargs > 0 else None,
            'max_varargs': arg.max_varargs if isinstance(arg, VarArgs) and arg.max_varargs > 0 else None,

            # Not yet supported
            'notes': [],
            'warnings': [],
        }

    def _generate_function(self, func: Function) -> J.Function:
        return {
            'name': func.name,
            'description': func.description,
            'since': func.since if func.since else None,
            'deprecated': func.deprecated if func.deprecated else None,
            'notes': func.notes,
            'warnings': func.warnings,
            'example': func.example if func.example else None,
            'returns': self._generate_type(func.returns),
            'returns_str': self._generate_type_str(func.returns),
            'posargs': {x.name: self._generate_arg(x) for x in func.posargs},
            'optargs': {x.name: self._generate_arg(x, True) for x in func.optargs},
            'kwargs': {x.name: self._generate_arg(x) for x in self.sorted_and_filtered(list(func.kwargs.values()))},
            'varargs': self._generate_arg(func.varargs) if func.varargs else None,
            'arg_flattening': func.arg_flattening,
        }

    def _generate_objects(self, obj: Object) -> J.Object:
        return {
            'name': obj.name,
            'description': obj.description,
            'since': obj.since if obj.since else None,
            'deprecated': obj.deprecated if obj.deprecated else None,
            'notes': obj.notes,
            'warnings': obj.warnings,
            'defined_by_module': obj.defined_by_module.name if obj.defined_by_module else None,
            'object_type': obj.obj_type.name,
            'is_container': obj.is_container,
            'example': obj.example if obj.example else None,
            'extends': obj.extends if obj.extends else None,
            'returned_by': [x.name for x in self.sorted_and_filtered(obj.returned_by)],
            'extended_by': [x.name for x in self.sorted_and_filtered(obj.extended_by)],
            'methods': {x.name: self._generate_function(x) for x in self.sorted_and_filtered(obj.methods)},
        }

    def generate(self) -> None:
        data: J.Root = {
            'version_major': J.VERSION_MAJOR,
            'version_minor': J.VERSION_MINOR,
            'meson_version': self._extract_meson_version(),
            'functions': {x.name: self._generate_function(x) for x in self.sorted_and_filtered(self.functions)},
            'objects': {x.name: self._generate_objects(x) for x in self.sorted_and_filtered(self.objects)},
            'objects_by_type': {
                'elementary': [x.name for x in self.elementary],
                'builtins': [x.name for x in self.builtins],
                'returned': [x.name for x in self.returned],
                'modules': {
                    x.name: [y.name for y in self.sorted_and_filtered(self.extract_returned_by_module(x))]
                    for x in self.modules
                },
            },
        }

        self.out.write_text(json.dumps(data), encoding='utf-8')
