# Copyright 2013-2021 The Meson development team
# Copyright © 2021 Intel Corporation

# 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 __future__ import annotations

import functools
import typing as T

from .base import DependencyException, DependencyMethods
from .base import process_method_kw
from .base import BuiltinDependency, SystemDependency
from .cmake import CMakeDependency
from .framework import ExtraFrameworkDependency
from .pkgconfig import PkgConfigDependency

if T.TYPE_CHECKING:
    from .base import ExternalDependency
    from .configtool import ConfigToolDependency
    from ..environment import Environment
    from ..mesonlib import MachineChoice

    DependencyGenerator = T.Callable[[], ExternalDependency]
    FactoryFunc = T.Callable[
        [
            'Environment',
            MachineChoice,
            T.Dict[str, T.Any],
            T.List[DependencyMethods]
        ],
        T.List[DependencyGenerator]
    ]

    WrappedFactoryFunc = T.Callable[
        [
            'Environment',
            MachineChoice,
            T.Dict[str, T.Any]
        ],
        T.List[DependencyGenerator]
    ]

    # This should be str, Environment, T.Dict[str, T.Any], T.Optional[str]
    # But if you try that, you get error: Cannot infer type of lambda
    CmakeDependencyFunc = T.Callable[..., CMakeDependency]

class DependencyFactory:

    """Factory to get dependencies from multiple sources.

    This class provides an initializer that takes a set of names and classes
    for various kinds of dependencies. When the initialized object is called
    it returns a list of callables return Dependency objects to try in order.

    :name: The name of the dependency. This will be passed as the name
        parameter of the each dependency unless it is overridden on a per
        type basis.
    :methods: An ordered list of DependencyMethods. This is the order
        dependencies will be returned in unless they are removed by the
        _process_method function
    :*_name: This will overwrite the name passed to the corresponding class.
        For example, if the name is 'zlib', but cmake calls the dependency
        'Z', then using `cmake_name='Z'` will pass the name as 'Z' to cmake.
    :*_class: A *type* or callable that creates a class, and has the
        signature of an ExternalDependency
    :system_class: If you pass DependencyMethods.SYSTEM in methods, you must
        set this argument.
    """

    def __init__(self, name: str, methods: T.List[DependencyMethods], *,
                 extra_kwargs: T.Optional[T.Dict[str, T.Any]] = None,
                 pkgconfig_name: T.Optional[str] = None,
                 pkgconfig_class: 'T.Type[PkgConfigDependency]' = PkgConfigDependency,
                 cmake_name: T.Optional[str] = None,
                 cmake_class: 'T.Union[T.Type[CMakeDependency], CmakeDependencyFunc]' = CMakeDependency,
                 configtool_class: 'T.Optional[T.Type[ConfigToolDependency]]' = None,
                 framework_name: T.Optional[str] = None,
                 framework_class: 'T.Type[ExtraFrameworkDependency]' = ExtraFrameworkDependency,
                 builtin_class: 'T.Type[BuiltinDependency]' = BuiltinDependency,
                 system_class: 'T.Type[SystemDependency]' = SystemDependency):

        if DependencyMethods.CONFIG_TOOL in methods and not configtool_class:
            raise DependencyException('A configtool must have a custom class')

        self.extra_kwargs = extra_kwargs or {}
        self.methods = methods
        self.classes: T.Dict[
            DependencyMethods,
            T.Callable[['Environment', T.Dict[str, T.Any]], ExternalDependency]
        ] = {
            # Just attach the correct name right now, either the generic name
            # or the method specific name.
            DependencyMethods.EXTRAFRAMEWORK: functools.partial(framework_class, framework_name or name),
            DependencyMethods.PKGCONFIG: functools.partial(pkgconfig_class, pkgconfig_name or name),
            DependencyMethods.CMAKE: functools.partial(cmake_class, cmake_name or name),
            DependencyMethods.SYSTEM: functools.partial(system_class, name),
            DependencyMethods.BUILTIN: functools.partial(builtin_class, name),
            DependencyMethods.CONFIG_TOOL: None,
        }
        if configtool_class is not None:
            self.classes[DependencyMethods.CONFIG_TOOL] = functools.partial(configtool_class, name)

    @staticmethod
    def _process_method(method: DependencyMethods, env: 'Environment', for_machine: MachineChoice) -> bool:
        """Report whether a method is valid or not.

        If the method is valid, return true, otherwise return false. This is
        used in a list comprehension to filter methods that are not possible.

        By default this only remove EXTRAFRAMEWORK dependencies for non-mac platforms.
        """
        # Extra frameworks are only valid for macOS and other apple products
        if (method is DependencyMethods.EXTRAFRAMEWORK and
                not env.machines[for_machine].is_darwin()):
            return False
        return True

    def __call__(self, env: 'Environment', for_machine: MachineChoice,
                 kwargs: T.Dict[str, T.Any]) -> T.List['DependencyGenerator']:
        """Return a list of Dependencies with the arguments already attached."""
        methods = process_method_kw(self.methods, kwargs)
        nwargs = self.extra_kwargs.copy()
        nwargs.update(kwargs)

        return [functools.partial(self.classes[m], env, nwargs) for m in methods
                if self._process_method(m, env, for_machine)]


def factory_methods(methods: T.Set[DependencyMethods]) -> T.Callable[['FactoryFunc'], 'WrappedFactoryFunc']:
    """Decorator for handling methods for dependency factory functions.

    This helps to make factory functions self documenting
    >>> @factory_methods([DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE])
    >>> def factory(env: Environment, for_machine: MachineChoice, kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
    >>>     pass
    """

    def inner(func: 'FactoryFunc') -> 'WrappedFactoryFunc':

        @functools.wraps(func)
        def wrapped(env: 'Environment', for_machine: MachineChoice, kwargs: T.Dict[str, T.Any]) -> T.List['DependencyGenerator']:
            return func(env, for_machine, kwargs, process_method_kw(methods, kwargs))

        return wrapped

    return inner
