# Copyright 2013-2021 The Meson development team

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from .. import mparser
from .exceptions import InvalidCode, InvalidArguments
from .helpers import flatten, resolve_second_level_holders
from .operator import MesonOperator
from ..mesonlib import HoldableObject, MesonBugException
import textwrap

import typing as T
from abc import ABCMeta

if T.TYPE_CHECKING:
    # Object holders need the actual interpreter
    from ..interpreter import Interpreter

TV_fw_var = T.Union[str, int, bool, list, dict, 'InterpreterObject']
TV_fw_args = T.List[T.Union[mparser.BaseNode, TV_fw_var]]
TV_fw_kwargs = T.Dict[str, T.Union[mparser.BaseNode, TV_fw_var]]

TV_func = T.TypeVar('TV_func', bound=T.Callable[..., T.Any])

TYPE_elementary = T.Union[str, int, bool, T.List[T.Any], T.Dict[str, T.Any]]
TYPE_var = T.Union[TYPE_elementary, HoldableObject, 'MesonInterpreterObject']
TYPE_nvar = T.Union[TYPE_var, mparser.BaseNode]
TYPE_kwargs = T.Dict[str, TYPE_var]
TYPE_nkwargs = T.Dict[str, TYPE_nvar]
TYPE_key_resolver = T.Callable[[mparser.BaseNode], str]

SubProject = T.NewType('SubProject', str)

if T.TYPE_CHECKING:
    from typing_extensions import Protocol
    __T = T.TypeVar('__T', bound=TYPE_var, contravariant=True)

    class OperatorCall(Protocol[__T]):
        def __call__(self, other: __T) -> TYPE_var: ...

class InterpreterObject:
    def __init__(self, *, subproject: T.Optional['SubProject'] = None) -> None:
        self.methods: T.Dict[
            str,
            T.Callable[[T.List[TYPE_var], TYPE_kwargs], TYPE_var]
        ] = {}
        self.operators: T.Dict[MesonOperator, 'OperatorCall'] = {}
        self.trivial_operators: T.Dict[
            MesonOperator,
            T.Tuple[
                T.Union[T.Type, T.Tuple[T.Type, ...]],
                'OperatorCall'
            ]
        ] = {}
        # Current node set during a method call. This can be used as location
        # when printing a warning message during a method call.
        self.current_node:  mparser.BaseNode = None
        self.subproject = subproject or SubProject('')

        # Some default operators supported by all objects
        self.operators.update({
            MesonOperator.EQUALS: self.op_equals,
            MesonOperator.NOT_EQUALS: self.op_not_equals,
        })

    # The type of the object that can be printed to the user
    def display_name(self) -> str:
        return type(self).__name__

    def method_call(
                self,
                method_name: str,
                args: T.List[TYPE_var],
                kwargs: TYPE_kwargs
            ) -> TYPE_var:
        if method_name in self.methods:
            method = self.methods[method_name]
            if not getattr(method, 'no-args-flattening', False):
                args = flatten(args)
            if not getattr(method, 'no-second-level-holder-flattening', False):
                args, kwargs = resolve_second_level_holders(args, kwargs)
            return method(args, kwargs)
        raise InvalidCode(f'Unknown method "{method_name}" in object {self} of type {type(self).__name__}.')

    def operator_call(self, operator: MesonOperator, other: TYPE_var) -> TYPE_var:
        if operator in self.trivial_operators:
            op = self.trivial_operators[operator]
            if op[0] is None and other is not None:
                raise MesonBugException(f'The unary operator `{operator.value}` of {self.display_name()} was passed the object {other} of type {type(other).__name__}')
            if op[0] is not None and not isinstance(other, op[0]):
                raise InvalidArguments(f'The `{operator.value}` operator of {self.display_name()} does not accept objects of type {type(other).__name__} ({other})')
            return op[1](other)
        if operator in self.operators:
            return self.operators[operator](other)
        raise InvalidCode(f'Object {self} of type {self.display_name()} does not support the `{operator.value}` operator.')

    # Default comparison operator support
    def _throw_comp_exception(self, other: TYPE_var, opt_type: str) -> T.NoReturn:
        raise InvalidArguments(textwrap.dedent(
            f'''
                Trying to compare values of different types ({self.display_name()}, {type(other).__name__}) using {opt_type}.
                This was deprecated and undefined behavior previously and is as of 0.60.0 a hard error.
            '''
        ))

    def op_equals(self, other: TYPE_var) -> bool:
        # We use `type(...) == type(...)` here to enforce an *exact* match for comparison. We
        # don't want comparisons to be possible where `isinstance(derived_obj, type(base_obj))`
        # would pass because this comparison must never be true: `derived_obj == base_obj`
        if type(self) != type(other):
            self._throw_comp_exception(other, '==')
        return self == other

    def op_not_equals(self, other: TYPE_var) -> bool:
        if type(self) != type(other):
            self._throw_comp_exception(other, '!=')
        return self != other

class MesonInterpreterObject(InterpreterObject):
    ''' All non-elementary objects and non-object-holders should be derived from this '''

class MutableInterpreterObject:
    ''' Dummy class to mark the object type as mutable '''

HoldableTypes = (HoldableObject, int, bool, str, list, dict)
TYPE_HoldableTypes = T.Union[TYPE_elementary, HoldableObject]
InterpreterObjectTypeVar = T.TypeVar('InterpreterObjectTypeVar', bound=TYPE_HoldableTypes)

class ObjectHolder(InterpreterObject, T.Generic[InterpreterObjectTypeVar]):
    def __init__(self, obj: InterpreterObjectTypeVar, interpreter: 'Interpreter') -> None:
        super().__init__(subproject=interpreter.subproject)
        # This causes some type checkers to assume that obj is a base
        # HoldableObject, not the specialized type, so only do this assert in
        # non-type checking situations
        if not T.TYPE_CHECKING:
            assert isinstance(obj, HoldableTypes), f'This is a bug: Trying to hold object of type `{type(obj).__name__}` that is not in `{HoldableTypes}`'
        self.held_object = obj
        self.interpreter = interpreter
        self.env = self.interpreter.environment

    # Hide the object holder abstraction from the user
    def display_name(self) -> str:
        return type(self.held_object).__name__

    # Override default comparison operators for the held object
    def op_equals(self, other: TYPE_var) -> bool:
        # See the comment from InterpreterObject why we are using `type()` here.
        if type(self.held_object) != type(other):
            self._throw_comp_exception(other, '==')
        return self.held_object == other

    def op_not_equals(self, other: TYPE_var) -> bool:
        if type(self.held_object) != type(other):
            self._throw_comp_exception(other, '!=')
        return self.held_object != other

    def __repr__(self) -> str:
        return f'<[{type(self).__name__}] holds [{type(self.held_object).__name__}]: {self.held_object!r}>'

class IterableObject(metaclass=ABCMeta):
    '''Base class for all objects that can be iterated over in a foreach loop'''

    def iter_tuple_size(self) -> T.Optional[int]:
        '''Return the size of the tuple for each iteration. Returns None if only a single value is returned.'''
        raise MesonBugException(f'iter_tuple_size not implemented for {self.__class__.__name__}')

    def iter_self(self) -> T.Iterator[T.Union[TYPE_var, T.Tuple[TYPE_var, ...]]]:
        raise MesonBugException(f'iter not implemented for {self.__class__.__name__}')

    def size(self) -> int:
        raise MesonBugException(f'size not implemented for {self.__class__.__name__}')
