# SPDX-License-Identifier: Apache-2.0
# Copyright 2013-2014 The Meson development team

from __future__ import annotations

import re
import typing as T

from . import coredata
from . import options
from . import mesonlib
from . import mparser
from . import mlog
from .interpreterbase import FeatureNew, FeatureDeprecated, typed_pos_args, typed_kwargs, ContainerTypeInfo, KwargInfo
from .interpreter.type_checking import NoneType, in_set_validator

if T.TYPE_CHECKING:
    from .interpreterbase import TYPE_var, TYPE_kwargs
    from .interpreterbase import SubProject
    from typing_extensions import TypedDict, Literal

    _DEPRECATED_ARGS = T.Union[bool, str, T.Dict[str, str], T.List[str]]

    FuncOptionArgs = TypedDict('FuncOptionArgs', {
        'type': str,
        'description': str,
        'yield': bool,
        'choices': T.Optional[T.List[str]],
        'value': object,
        'min': T.Optional[int],
        'max': T.Optional[int],
        'deprecated': _DEPRECATED_ARGS,
        })

    class StringArgs(TypedDict):
        value: str

    class BooleanArgs(TypedDict):
        value: bool

    class ComboArgs(TypedDict):
        value: str
        choices: T.List[str]

    class IntegerArgs(TypedDict):
        value: int
        min: T.Optional[int]
        max: T.Optional[int]

    class StringArrayArgs(TypedDict):
        value: T.Optional[T.Union[str, T.List[str]]]
        choices: T.List[str]

    class FeatureArgs(TypedDict):
        value: Literal['enabled', 'disabled', 'auto']
        choices: T.List[str]


class OptionException(mesonlib.MesonException):
    pass


optname_regex = re.compile('[^a-zA-Z0-9_-]')


class OptionInterpreter:
    def __init__(self, subproject: 'SubProject') -> None:
        self.options: 'coredata.MutableKeyedOptionDictType' = {}
        self.subproject = subproject
        self.option_types: T.Dict[str, T.Callable[..., options.UserOption]] = {
            'string': self.string_parser,
            'boolean': self.boolean_parser,
            'combo': self.combo_parser,
            'integer': self.integer_parser,
            'array': self.string_array_parser,
            'feature': self.feature_parser,
        }

    def process(self, option_file: str) -> None:
        try:
            with open(option_file, encoding='utf-8') as f:
                code = f.read()
        except UnicodeDecodeError as e:
            raise mesonlib.MesonException(f'Malformed option file {option_file!r} failed to parse as unicode: {e}')
        try:
            ast = mparser.Parser(code, option_file).parse()
        except mesonlib.MesonException as me:
            me.file = option_file
            raise me
        if not isinstance(ast, mparser.CodeBlockNode):
            e = OptionException('Option file is malformed.')
            e.lineno = ast.lineno()
            e.file = option_file
            raise e
        for cur in ast.lines:
            try:
                self.current_node = cur
                self.evaluate_statement(cur)
            except mesonlib.MesonException as e:
                e.lineno = cur.lineno
                e.colno = cur.colno
                e.file = option_file
                raise e
            except Exception as e:
                raise mesonlib.MesonException(
                    str(e), lineno=cur.lineno, colno=cur.colno, file=option_file)

    def reduce_single(self, arg: T.Union[str, mparser.BaseNode]) -> 'TYPE_var':
        if isinstance(arg, str):
            return arg
        if isinstance(arg, mparser.ParenthesizedNode):
            return self.reduce_single(arg.inner)
        elif isinstance(arg, (mparser.StringNode, mparser.BooleanNode, mparser.NumberNode)):
            return arg.value
        elif isinstance(arg, mparser.ArrayNode):
            return [self.reduce_single(curarg) for curarg in arg.args.arguments]
        elif isinstance(arg, mparser.DictNode):
            d = {}
            for k, v in arg.args.kwargs.items():
                if not isinstance(k, mparser.StringNode):
                    raise OptionException('Dictionary keys must be a string literal')
                d[k.value] = self.reduce_single(v)
            return d
        elif isinstance(arg, mparser.UMinusNode):
            res = self.reduce_single(arg.value)
            if not isinstance(res, (int, float)):
                raise OptionException('Token after "-" is not a number')
            FeatureNew.single_use('negative numbers in meson_options.txt', '0.54.1', self.subproject)
            return -res
        elif isinstance(arg, mparser.NotNode):
            res = self.reduce_single(arg.value)
            if not isinstance(res, bool):
                raise OptionException('Token after "not" is not a a boolean')
            FeatureNew.single_use('negation ("not") in meson_options.txt', '0.54.1', self.subproject)
            return not res
        elif isinstance(arg, mparser.ArithmeticNode):
            l = self.reduce_single(arg.left)
            r = self.reduce_single(arg.right)
            if not (arg.operation == 'add' and isinstance(l, str) and isinstance(r, str)):
                raise OptionException('Only string concatenation with the "+" operator is allowed')
            FeatureNew.single_use('string concatenation in meson_options.txt', '0.55.0', self.subproject)
            return l + r
        else:
            raise OptionException('Arguments may only be string, int, bool, or array of those.')

    def reduce_arguments(self, args: mparser.ArgumentNode) -> T.Tuple['TYPE_var', 'TYPE_kwargs']:
        if args.incorrect_order():
            raise OptionException('All keyword arguments must be after positional arguments.')
        reduced_pos = [self.reduce_single(arg) for arg in args.arguments]
        reduced_kw = {}
        for key in args.kwargs.keys():
            if not isinstance(key, mparser.IdNode):
                raise OptionException('Keyword argument name is not a string.')
            a = args.kwargs[key]
            reduced_kw[key.value] = self.reduce_single(a)
        return reduced_pos, reduced_kw

    def evaluate_statement(self, node: mparser.BaseNode) -> None:
        if not isinstance(node, mparser.FunctionNode):
            raise OptionException('Option file may only contain option definitions')
        func_name = node.func_name.value
        if func_name != 'option':
            raise OptionException('Only calls to option() are allowed in option files.')
        (posargs, kwargs) = self.reduce_arguments(node.args)
        self.func_option(posargs, kwargs)

    @typed_kwargs(
        'option',
        KwargInfo(
            'type',
            str,
            required=True,
            validator=in_set_validator({'string', 'boolean', 'integer', 'combo', 'array', 'feature'})
        ),
        KwargInfo('description', str, default=''),
        KwargInfo(
            'deprecated',
            (bool, str, ContainerTypeInfo(dict, str), ContainerTypeInfo(list, str)),
            default=False,
            since='0.60.0',
            since_values={str: '0.63.0'},
        ),
        KwargInfo('yield', bool, default=options.DEFAULT_YIELDING, since='0.45.0'),
        allow_unknown=True,
    )
    @typed_pos_args('option', str)
    def func_option(self, args: T.Tuple[str], kwargs: 'FuncOptionArgs') -> None:
        opt_name = args[0]
        if optname_regex.search(opt_name) is not None:
            raise OptionException('Option names can only contain letters, numbers or dashes.')
        key = mesonlib.OptionKey.from_string(opt_name).evolve(subproject=self.subproject)
        if not key.is_project():
            raise OptionException('Option name %s is reserved.' % opt_name)

        opt_type = kwargs['type']
        parser = self.option_types[opt_type]
        description = kwargs['description'] or opt_name

        # Drop the arguments we've already consumed
        n_kwargs = {k: v for k, v in kwargs.items()
                    if k not in {'type', 'description', 'deprecated', 'yield'}}

        opt = parser(opt_name, description, (kwargs['yield'], kwargs['deprecated']), n_kwargs)
        if key in self.options:
            mlog.deprecation(f'Option {opt_name} already exists.')
        self.options[key] = opt

    @typed_kwargs(
        'string option',
        KwargInfo('value', str, default=''),
    )
    def string_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArgs) -> options.UserOption:
        return options.UserStringOption(name, description, kwargs['value'], *args)

    @typed_kwargs(
        'boolean option',
        KwargInfo(
            'value',
            (bool, str),
            default=True,
            validator=lambda x: None if isinstance(x, bool) or x in {'true', 'false'} else 'boolean options must have boolean values',
            deprecated_values={str: ('1.1.0', 'use a boolean, not a string')},
        ),
    )
    def boolean_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: BooleanArgs) -> options.UserOption:
        return options.UserBooleanOption(name, description, kwargs['value'], *args)

    @typed_kwargs(
        'combo option',
        KwargInfo('value', (str, NoneType)),
        KwargInfo('choices', ContainerTypeInfo(list, str, allow_empty=False), required=True),
    )
    def combo_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: ComboArgs) -> options.UserOption:
        choices = kwargs['choices']
        value = kwargs['value']
        if value is None:
            value = kwargs['choices'][0]
        return options.UserComboOption(name, description, choices, value, *args)

    @typed_kwargs(
        'integer option',
        KwargInfo(
            'value',
            (int, str),
            default=True,
            deprecated_values={str: ('1.1.0', 'use an integer, not a string')},
            convertor=int,
        ),
        KwargInfo('min', (int, NoneType)),
        KwargInfo('max', (int, NoneType)),
    )
    def integer_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: IntegerArgs) -> options.UserOption:
        value = kwargs['value']
        inttuple = (kwargs['min'], kwargs['max'], value)
        return options.UserIntegerOption(name, description, inttuple, *args)

    @typed_kwargs(
        'string array option',
        KwargInfo('value', (ContainerTypeInfo(list, str), str, NoneType)),
        KwargInfo('choices', ContainerTypeInfo(list, str), default=[]),
    )
    def string_array_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArrayArgs) -> options.UserOption:
        choices = kwargs['choices']
        value = kwargs['value'] if kwargs['value'] is not None else choices
        if isinstance(value, str):
            if value.startswith('['):
                FeatureDeprecated('String value for array option', '1.3.0').use(self.subproject)
            else:
                raise mesonlib.MesonException('Value does not define an array: ' + value)
        return options.UserArrayOption(name, description, value,
                                       choices=choices,
                                       yielding=args[0],
                                       deprecated=args[1])

    @typed_kwargs(
        'feature option',
        KwargInfo('value', str, default='auto', validator=in_set_validator({'auto', 'enabled', 'disabled'})),
    )
    def feature_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: FeatureArgs) -> options.UserOption:
        return options.UserFeatureOption(name, description, kwargs['value'], *args)
