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

# This file contains the base representation for import('modname')

from __future__ import annotations
import dataclasses
import os.path
import typing as T

from .. import build, dependencies, mesonlib, mlog
from ..options import OptionKey
from ..build import IncludeDirs
from ..interpreterbase.decorators import noKwargs, noPosargs
from ..mesonlib import relpath, HoldableObject, MachineChoice
from ..programs import ExternalProgram

if T.TYPE_CHECKING:
    from ..compilers.compilers import Language
    from ..dependencies.base import DependencyObjectKWs
    from ..interpreter import Interpreter
    from ..interpreter.interpreter import ProgramVersionFunc
    from ..interpreterbase import TYPE_var, TYPE_kwargs
    from ..programs import Program
    from ..dependencies import Dependency
    from ..options import ElementaryOptionValues

class ModuleState:
    """Object passed to all module methods.

    This is a WIP API provided to modules, it should be extended to have everything
    needed so modules does not touch any other part of Meson internal APIs.
    """

    def __init__(self, interpreter: 'Interpreter') -> None:
        # Keep it private, it should be accessed only through methods.
        self._interpreter = interpreter

        self.source_root = interpreter.environment.get_source_dir()
        self.build_to_src = relpath(interpreter.environment.get_source_dir(),
                                    interpreter.environment.get_build_dir())
        self.subproject_dir = interpreter.subproject_dir
        self.subproject = interpreter.subproject
        self.subdir = interpreter.subdir
        self.root_subdir = interpreter.root_subdir
        self.current_lineno = interpreter.current_node.lineno
        self.environment = interpreter.environment
        self.project_name = interpreter.active_projectname
        self.project_version = interpreter.project_version
        # The backend object is under-used right now, but we will need it:
        # https://github.com/mesonbuild/meson/issues/1419
        self.backend = interpreter.backend
        self.dependency_overrides = interpreter.build.dependency_overrides
        self.targets = interpreter.build.targets
        self.data = interpreter.build.data
        self.headers = interpreter.build.get_headers()
        self.man = interpreter.build.get_man()
        self.global_args = interpreter.build.global_args.host
        self.project_args = interpreter.current_build_project().project_args.host
        self.current_node = interpreter.current_node
        self.machine_map = interpreter.build.machine_map
        self.current_build_project = interpreter.current_build_project()

    def get_include_args(self, include_dirs: T.Iterable[T.Union[str, build.IncludeDirs]], implicit: bool = False, prefix: str = '-I') -> T.List[str]:
        srcdir = self.environment.get_source_dir()
        builddir = self.environment.get_build_dir()

        dirs_str: T.List[str] = []
        for dirs in include_dirs:
            if isinstance(dirs, str):
                dirs_str += [f'{prefix}{dirs}']
            else:
                dirs_str.extend([f'{prefix}{i}' for i in dirs.abs_string_list(srcdir, builddir)])

        if implicit:
            build_cur_dir = os.path.normpath(os.path.join(builddir, self.subdir))
            dirs_str.append(f'{prefix}{build_cur_dir}')
            source_cur_dir = os.path.normpath(os.path.join(srcdir, self.subdir))
            dirs_str.append(f'{prefix}{source_cur_dir}')
        return dirs_str

    def find_program(self, prog: T.Union[mesonlib.FileOrString, T.List[mesonlib.FileOrString]],
                     required: bool = True,
                     version_func: T.Optional[ProgramVersionFunc] = None,
                     wanted: T.Union[str, T.List[str]] = '', silent: bool = False,
                     for_machine: MachineChoice = MachineChoice.HOST) -> Program:
        if not isinstance(prog, list):
            prog = [prog]
        return self._interpreter.find_program_impl(prog, required=required, version_func=version_func,
                                                   wanted=wanted, silent=silent, for_machine=for_machine)

    def find_tool(self, name: str, depname: str, varname: str, required: bool = True,
                  wanted: T.Optional[str] = None, native: bool = True) -> Program:
        # Look in overrides in case it's built as subproject
        for_machine = MachineChoice.BUILD if native else MachineChoice.HOST
        progobj = self._interpreter.program_from_overrides([name], for_machine, [])
        if progobj is not None:
            return progobj

        # Look in machine file
        prog_list = self.environment.lookup_binary_entry(MachineChoice.HOST, name)
        if prog_list is not None:
            return ExternalProgram.from_entry(name, prog_list)

        # Check if pkgconfig has a variable
        dep = self.dependency(depname, native=native, required=False, wanted=wanted)
        if dep.found() and dep.type_name == 'pkgconfig':
            value = dep.get_variable(pkgconfig=varname)
            if value:
                progobj = ExternalProgram(value)
                if not progobj.found():
                    msg = (f'Dependency {depname!r} tool variable {varname!r} contains erroneous value: {value!r}\n\n'
                           f'This is a distributor issue -- please report it to your {depname} provider.')
                    raise mesonlib.MesonException(msg)
                return progobj

        # Normal program lookup
        return self.find_program(name, required=required, wanted=wanted)

    def override_dependency(self, depname: str, dep: Dependency, static: T.Optional[bool] = None,
                            for_machine: MachineChoice = MachineChoice.HOST) -> None:
        kwargs: DependencyObjectKWs = {'native': for_machine}
        if static is not None:
            kwargs['static'] = static
        identifier = dependencies.get_dep_identifier(depname, kwargs)
        override = self.dependency_overrides[for_machine].get(identifier)
        if override:
            m = 'Tried to override dependency {!r} which has already been resolved or overridden at {}'
            location = mlog.get_error_location_string(override.node.filename, override.node.lineno)
            raise mesonlib.MesonException(m.format(depname, location))
        self.dependency_overrides[for_machine][identifier] = \
            build.DependencyOverride(dep, self._interpreter.current_node)

    def overridden_dependency(self, depname: str, for_machine: MachineChoice = MachineChoice.HOST) -> Dependency:
        identifier = dependencies.get_dep_identifier(depname, {'native': for_machine})
        try:
            return self.dependency_overrides[for_machine][identifier].dep
        except KeyError:
            raise mesonlib.MesonException(f'dependency "{depname}" was not overridden for the {for_machine}')

    def dependency(self, depname: str, native: bool = False, required: bool = True,
                   wanted: T.Optional[T.Union[str, T.List[str]]] = None) -> 'Dependency':
        kwargs: T.Dict[str, object] = {'native': native, 'required': required}
        if wanted:
            kwargs['version'] = wanted
        # FIXME: Even if we fix the function, mypy still can't figure out what's
        # going on here. And we really don't want to call interpreter
        # implementations of meson functions anyway.
        return self._interpreter.func_dependency(self.current_node, [depname], kwargs) # type: ignore

    def test(self, args: T.Tuple[str, T.Union[build.Executable, build.Jar, Program, mesonlib.File]],
             workdir: T.Optional[str] = None,
             env: T.Union[T.List[str], T.Dict[str, str], str] = None,
             depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]] = None) -> None:
        kwargs = {'workdir': workdir,
                  'env': env,
                  'depends': depends,
                  }
        # typed_* takes a list, and gives a tuple to func_test. Violating that constraint
        # makes the universe (or at least use of this function) implode
        real_args = list(args)
        # TODO: Use interpreter internal API, but we need to go through @typed_kwargs
        self._interpreter.func_test(self.current_node, real_args, kwargs)

    def get_option(self, name: str, subproject: str = '',
                   machine: MachineChoice = MachineChoice.HOST) -> ElementaryOptionValues:
        return self.environment.coredata.optstore.get_value_for(OptionKey(name, subproject, machine))

    def is_user_defined_option(self, name: str, subproject: str = '',
                               machine: MachineChoice = MachineChoice.HOST,
                               lang: T.Optional[str] = None) -> bool:
        key = OptionKey(name, subproject, machine)
        return key in self._interpreter.user_defined_options.cmd_line_options

    def process_include_dirs(self, dirs: T.Iterable[T.Union[str, IncludeDirs]]) -> T.Iterable[IncludeDirs]:
        """Convert raw include directory arguments to only IncludeDirs

        :param dirs: An iterable of strings and IncludeDirs
        :return: None
        :yield: IncludeDirs objects
        """
        for d in dirs:
            if isinstance(d, IncludeDirs):
                yield d
            else:
                yield self._interpreter.build_incdir_object([d])

    def add_language(self, lang: Language, for_machine: MachineChoice) -> None:
        self._interpreter.add_languages([lang], True, for_machine)

class ModuleObject(HoldableObject):
    """Base class for all objects returned by modules
    """
    def __init__(self) -> None:
        self.methods: T.Dict[
            str,
            T.Callable[[ModuleState, T.List['TYPE_var'], 'TYPE_kwargs'], T.Union[ModuleReturnValue, 'TYPE_var']]
        ] = {}


class MutableModuleObject(ModuleObject):
    pass


@dataclasses.dataclass
class ModuleInfo:

    """Metadata about a Module."""

    name: str
    added: T.Optional[str] = None
    deprecated: T.Optional[str] = None
    unstable: bool = False
    stabilized: T.Optional[str] = None


class NewExtensionModule(ModuleObject):

    """Class for modern modules

    provides the found method.
    """

    INFO: ModuleInfo

    def __init__(self) -> None:
        super().__init__()
        self.methods.update({
            'found': self.found_method,
        })

    @noPosargs
    @noKwargs
    def found_method(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
        return self.found()

    @staticmethod
    def found() -> bool:
        return True

    def postconf_hook(self, b: build.Build) -> None:
        pass

# FIXME: Port all modules to stop using self.interpreter and use API on
# ModuleState instead. Modules should stop using this class and instead use
# ModuleObject base class.
class ExtensionModule(NewExtensionModule):
    def __init__(self, interpreter: 'Interpreter') -> None:
        super().__init__()
        self.interpreter = interpreter

class NotFoundExtensionModule(NewExtensionModule):

    """Class for modern modules

    provides the found method.
    """

    def __init__(self, name: str) -> None:
        super().__init__()
        self.INFO = ModuleInfo(name)

    @staticmethod
    def found() -> bool:
        return False


def is_module_library(fname: mesonlib.FileOrString) -> bool:
    '''
    Check if the file is a library-like file generated by a module-specific
    target, such as GirTarget or TypelibTarget
    '''
    suffix = fname.split('.')[-1]
    return suffix in {'gir', 'typelib'}


class ModuleReturnValue:
    def __init__(self, return_value: T.Optional[TYPE_var],
                 new_objects: T.Sequence[T.Union[TYPE_var, mesonlib.InstallScript]]) -> None:
        self.return_value = return_value
        assert isinstance(new_objects, list)
        self.new_objects: T.List[T.Union[TYPE_var, mesonlib.InstallScript]] = new_objects

class GResourceTarget(build.CustomTarget):
    source_dirs: T.List[str] = []

class GResourceHeaderTarget(build.CustomTarget):
    pass

class GirTarget(build.CustomTarget):
    pass

class TypelibTarget(build.CustomTarget):
    pass

class VapiTarget(build.CustomTarget):
    pass
