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

from __future__ import annotations

from .base import ExternalDependency, DependencyException, DependencyTypeName
from .pkgconfig import PkgConfigDependency
from ..mesonlib import (Popen_safe, join_args, version_compare, version_compare_many)
from ..options import OptionKey
from ..programs import ExternalProgram
from .. import mlog
from enum import Enum
import re
import os
import json
import typing as T

if T.TYPE_CHECKING:
    from typing_extensions import TypedDict

    from ..environment import Environment
    from .base import DependencyObjectKWs

    # Definition of what `dub describe` returns (only the fields used by Meson)
    class DubDescription(TypedDict):
        platform: T.List[str]
        architecture: T.List[str]
        buildType: str
        packages: T.List[DubPackDesc]
        targets: T.List[DubTargetDesc]

    class DubPackDesc(TypedDict):
        name: str
        version: str
        active: bool
        configuration: str
        path: str
        targetType: str
        targetFileName: str

    class DubTargetDesc(TypedDict):
        rootPackage: str
        linkDependencies: T.List[str]
        buildSettings: DubBuildSettings
        cacheArtifactPath: str

    class DubBuildSettings(TypedDict):
        importPaths: T.List[str]
        stringImportPaths: T.List[str]
        versions: T.List[str]
        mainSourceFile: str
        sourceFiles: T.List[str]
        dflags: T.List[str]
        libs: T.List[str]
        lflags: T.List[str]

    class FindTargetEntry(TypedDict):
        search: str
        artifactPath: str

class DubDescriptionSource(Enum):
    Local = 'local'
    External = 'external'

class DubDependency(ExternalDependency):
    # dub program and version
    class_dubbin: T.Optional[T.Tuple[ExternalProgram, str]] = None
    class_dubbin_searched = False
    class_cache_dir = ''

    type_name = DependencyTypeName('dub')

    # Map Meson Compiler ID's to Dub Compiler ID's
    _ID_MAP: T.Mapping[str, str] = {
        'dmd': 'dmd',
        'gcc': 'gdc',
        'llvm': 'ldc',
    }

    def __init__(self, name: str, environment: 'Environment', kwargs: DependencyObjectKWs):
        kwargs['language'] = 'd'
        super().__init__(name, environment, kwargs)
        from ..compilers.d import DCompiler, d_feature_args

        _temp_comp = super().get_compiler()
        assert isinstance(_temp_comp, DCompiler)
        self.compiler = _temp_comp

        if kwargs.get('required') is not None:
            self.required = kwargs['required']

        if DubDependency.class_dubbin is None and not DubDependency.class_dubbin_searched:
            DubDependency.class_dubbin = self._check_dub()
            DubDependency.class_dubbin_searched = True
        if DubDependency.class_dubbin is None:
            if self.required:
                raise DependencyException('DUB not found.')
            return

        (self.dubbin, dubver) = DubDependency.class_dubbin  # pylint: disable=unpacking-non-sequence

        assert isinstance(self.dubbin, ExternalProgram)

        # Check Dub's compatibility with Meson
        self._search_in_cache = version_compare(dubver, '<=1.31.1')
        self._use_cache_describe = version_compare(dubver, '>=1.35.0')
        self._dub_has_build_deep = version_compare(dubver, '>=1.35.0')

        if not self._search_in_cache and not self._use_cache_describe:
            if self.required:
                raise DependencyException(
                    f'DUB version {dubver} is not compatible with Meson'
                    " (can't locate artifacts in DUB's cache). Upgrade to Dub >= 1.35.")
            else:
                mlog.warning(f'DUB dependency {name} not found because Dub {dubver} '
                             "is not compatible with Meson. (Can't locate artifacts in DUB's cache)."
                             ' Upgrade to Dub >= 1.35')
            return

        mlog.debug('Determining dependency {!r} with DUB executable '
                   '{!r}'.format(name, self.dubbin.get_path()))

        # we need to know the target architecture
        dub_arch = self.compiler.arch

        # we need to know the build type as well
        dub_buildtype = str(environment.coredata.optstore.get_value_for(OptionKey('buildtype')))
        # MESON types: choices=['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'])),
        # DUB types: debug (default), plain, release, release-debug, release-nobounds, unittest, profile, profile-gc,
        # docs, ddox, cov, unittest-cov, syntax and custom
        if dub_buildtype == 'debugoptimized':
            dub_buildtype = 'release-debug'
        elif dub_buildtype == 'minsize':
            dub_buildtype = 'release'

        result = self._get_dub_description(dub_arch, dub_buildtype)
        if result is None:
            return
        description, build_cmd, description_source = result
        dub_comp_id = self._ID_MAP[self.compiler.get_id()]

        self.compile_args = []
        self.link_args = self.raw_link_args = []

        show_buildtype_warning = False

        # collect all targets
        targets = {t['rootPackage']: t for t in description['targets']}

        def find_package_target(pkg: DubPackDesc) -> bool:
            nonlocal show_buildtype_warning
            # try to find a static library in a DUB folder corresponding to
            # version, configuration, compiler, arch and build-type
            # if can find, add to link_args.
            # link_args order is meaningful, so this function MUST be called in the right order
            pack_id = f'{pkg["name"]}@{pkg["version"]}'
            tgt_desc = targets[pkg['name']]
            (tgt_file, compatibilities) = self._find_target_in_cache(description, pkg, tgt_desc, dub_comp_id)
            if tgt_file is None:
                if not compatibilities:
                    mlog.error(mlog.bold(pack_id), 'not found')
                elif 'compiler' not in compatibilities:
                    mlog.error(mlog.bold(pack_id), 'found but not compiled with ', mlog.bold(dub_comp_id))
                elif dub_comp_id != 'gdc' and 'compiler_version' not in compatibilities:
                    mlog.error(mlog.bold(pack_id), 'found but not compiled with',
                               mlog.bold(f'{dub_comp_id}-{self.compiler.version}'))
                elif 'arch' not in compatibilities:
                    mlog.error(mlog.bold(pack_id), 'found but not compiled for', mlog.bold(dub_arch))
                elif 'platform' not in compatibilities:
                    mlog.error(mlog.bold(pack_id), 'found but not compiled for',
                               mlog.bold('.'.join(description['platform'])))
                elif 'configuration' not in compatibilities:
                    mlog.error(mlog.bold(pack_id), 'found but not compiled for the',
                               mlog.bold(pkg['configuration']), 'configuration')
                else:
                    mlog.error(mlog.bold(pack_id), 'not found')

                mlog.log('You may try the following command to install the necessary DUB libraries:')
                mlog.log(mlog.bold(build_cmd))

                return False

            if 'build_type' not in compatibilities:
                mlog.warning(mlog.bold(pack_id), 'found but not compiled as', mlog.bold(dub_buildtype))
                show_buildtype_warning = True

            self.link_args.append(tgt_file)
            return True

        # Main algorithm:
        # 1. Ensure that the target is a compatible library type (not dynamic)
        # 2. Find a compatible built library for the main dependency
        # 3. Do the same for each sub-dependency.
        #    link_args MUST be in the same order than the "linkDependencies" of the main target
        # 4. Add other build settings (imports, versions etc.)

        # 1
        packages: T.Dict[str, DubPackDesc] = {}
        found_it = False
        for pkg in description['packages']:
            packages[pkg['name']] = pkg

            if not pkg['active']:
                continue

            # check that the main dependency is indeed a library
            if pkg['name'] == name:
                if pkg['targetType'] not in ['library', 'sourceLibrary', 'staticLibrary']:
                    mlog.error(mlog.bold(name), "found but it isn't a static library, it is:",
                               pkg['targetType'])
                    return

                if self.version_reqs is not None:
                    ver = pkg['version']
                    if not version_compare_many(ver, self.version_reqs)[0]:
                        mlog.error(mlog.bold(f'{name}@{ver}'),
                                   'does not satisfy all version requirements of:',
                                   ' '.join(self.version_reqs))
                        return

                found_it = True
                self.version = pkg['version']
                self.pkg = pkg

        if not found_it:
            mlog.error(f'Could not find {name} in DUB description.')
            if description_source is DubDescriptionSource.Local:
                mlog.log('Make sure that the dependency is registered for your dub project by running:')
                mlog.log(mlog.bold(f'dub add {name}'))
            elif description_source is DubDescriptionSource.External:
                # `dub describe pkg` did not contain the pkg
                raise RuntimeError(f'`dub describe` succeeded but it does not contains {name}')
            return

        if name not in targets:
            if self.pkg['targetType'] == 'sourceLibrary':
                # source libraries have no associated targets,
                # but some build settings like import folders must be found from the package object.
                # Current algo only get these from "buildSettings" in the target object.
                # Let's save this for a future PR.
                # (See openssl DUB package for example of sourceLibrary)
                mlog.error('DUB targets of type', mlog.bold('sourceLibrary'), 'are not supported.')
            else:
                mlog.error('Could not find target description for', mlog.bold(self.name))
            return

        # Current impl only supports static libraries
        self.static = True

        # 2
        if not find_package_target(self.pkg):
            return

        # 3
        for link_dep in targets[name]['linkDependencies']:
            pkg = packages[link_dep]
            if not find_package_target(pkg):
                return

        if show_buildtype_warning:
            mlog.log('If it is not suitable, try the following command and reconfigure Meson with', mlog.bold('--clearcache'))
            mlog.log(mlog.bold(build_cmd))

        # 4
        bs = targets[name]['buildSettings']

        for flag in bs['dflags']:
            self.compile_args.append(flag)

        for path in bs['importPaths']:
            self.compile_args.append('-I' + path)

        for path in bs['stringImportPaths']:
            if 'import_dir' not in d_feature_args[self.compiler.id]:
                break
            flag = d_feature_args[self.compiler.id]['import_dir']
            self.compile_args.append(f'{flag}={path}')

        for ver in bs['versions']:
            if 'version' not in d_feature_args[self.compiler.id]:
                break
            flag = d_feature_args[self.compiler.id]['version']
            self.compile_args.append(f'{flag}={ver}')

        if bs['mainSourceFile']:
            self.compile_args.append(bs['mainSourceFile'])

        # pass static libraries
        # linkerFiles are added during step 3
        # for file in bs['linkerFiles']:
        #     self.link_args.append(file)

        for file in bs['sourceFiles']:
            # sourceFiles may contain static libraries
            if file.endswith('.lib') or file.endswith('.a'):
                self.link_args.append(file)

        for flag in bs['lflags']:
            self.link_args.append(flag)

        is_windows = self.env.machines.host.is_windows()
        if is_windows:
            winlibs = ['kernel32', 'user32', 'gdi32', 'winspool', 'shell32', 'ole32',
                       'oleaut32', 'uuid', 'comdlg32', 'advapi32', 'ws2_32']

        for lib in bs['libs']:
            if os.name != 'nt':
                # trying to add system libraries by pkg-config
                pkgdep = PkgConfigDependency(lib, environment, {'required': True, 'silent': True, 'native': self.for_machine})
                if pkgdep.is_found:
                    for arg in pkgdep.get_compile_args():
                        self.compile_args.append(arg)
                    for arg in pkgdep.get_link_args():
                        self.link_args.append(arg)
                    for arg in pkgdep.get_link_args(raw=True):
                        self.raw_link_args.append(arg)
                    continue

            if is_windows and lib in winlibs:
                self.link_args.append(lib + '.lib')
                continue

            # fallback
            self.link_args.append('-l'+lib)

        self.is_found = True

    # Get the dub description needed to resolve the dependency and a
    # build command that can be used to build the dependency in case it is
    # not present.
    def _get_dub_description(self, dub_arch: str, dub_buildtype: str) -> T.Optional[T.Tuple[DubDescription, str, DubDescriptionSource]]:
        def get_build_command() -> T.List[str]:
            if self._dub_has_build_deep:
                cmd = ['dub', 'build', '--deep']
            else:
                cmd = ['dub', 'run', '--yes', 'dub-build-deep', '--']

            return cmd + [
                '--arch=' + dub_arch,
                '--compiler=' + self.compiler.get_exelist()[-1],
                '--build=' + dub_buildtype,
            ]

        # Ask dub for the package
        describe_cmd = [
            'describe', '--arch=' + dub_arch,
            '--build=' + dub_buildtype, '--compiler=' + self.compiler.get_exelist()[-1]
        ]
        helper_build = join_args(get_build_command())
        source = DubDescriptionSource.Local
        ret, res, err = self._call_dubbin(describe_cmd)
        if ret == 0:
            return (json.loads(res), helper_build, source)
        else:
            mlog.debug('DUB describe (raw) failed: ' + err)

        pack_spec = self.name
        if self.version_reqs is not None:
            if len(self.version_reqs) > 1:
                mlog.error('Multiple version requirements are not supported for raw dub dependencies.')
                mlog.error("Please specify only an exact version like '1.2.3'")
                raise DependencyException('Multiple version requirements are not solvable for raw dub dependencies')
            elif len(self.version_reqs) == 1:
                pack_spec += '@' + self.version_reqs[0]

        describe_cmd = [
            'describe', pack_spec, '--arch=' + dub_arch,
            '--build=' + dub_buildtype, '--compiler=' + self.compiler.get_exelist()[-1]
        ]
        helper_build = join_args(get_build_command() + [pack_spec])
        source = DubDescriptionSource.External
        ret, res, err = self._call_dubbin(describe_cmd)
        if ret == 0:
            return (json.loads(res), helper_build, source)

        mlog.debug('DUB describe failed: ' + err)
        if 'locally' in err:
            mlog.error(mlog.bold(pack_spec), 'is not present locally. You may try the following command:')
            mlog.log(mlog.bold(helper_build))
        return None

    # This function finds the target of the provided JSON package, built for the right
    # compiler, architecture, configuration...
    # It returns (target|None, {compatibilities})
    # If None is returned for target, compatibilities will list what other targets were found without full compatibility
    def _find_target_in_cache(self, desc: DubDescription, pkg_desc: DubPackDesc,
                              tgt_desc: DubTargetDesc, dub_comp_id: str
                              ) -> T.Tuple[T.Optional[str], T.Set[str]]:
        mlog.debug('Searching in DUB cache for compatible', pkg_desc['targetFileName'])

        # recent DUB versions include a direct path to a compatible cached artifact
        if self._use_cache_describe:
            tgt_file = tgt_desc['cacheArtifactPath']
            if os.path.exists(tgt_file):
                return (tgt_file, {'configuration', 'platform', 'arch', 'compiler', 'compiler_version', 'build_type'})
            else:
                return (None, set())

        assert self._search_in_cache

        # try to find a string like library-debug-linux.posix-x86_64-ldc_2081-EF934983A3319F8F8FF2F0E107A363BA

        # fields are:
        #  - configuration
        #  - build type
        #  - platform
        #  - architecture
        #  - compiler id (dmd, ldc, gdc)
        #  - compiler version or frontend id or frontend version?

        comp_versions = self._get_comp_versions_to_find(dub_comp_id)

        # build_type is not in check_list because different build types might be compatible.
        # We do show a WARNING that the build type is not the same.
        # It might be critical in release builds, and acceptable otherwise
        check_list = {'configuration', 'platform', 'arch', 'compiler', 'compiler_version'}
        compatibilities: T.Set[str] = set()

        for entry in self._cache_entries(pkg_desc):
            target = entry['artifactPath']
            if not os.path.exists(target):
                # unless Dub and Meson are racing, the target file should be present
                # when the directory is present
                mlog.debug("WARNING: Could not find a Dub target: " + target)
                continue

            # we build a new set for each entry, because if this target is returned
            # we want to return only the compatibilities associated to this target
            # otherwise we could miss the WARNING about build_type
            comps: T.Set[str] = set()

            search = entry['search']

            mlog.debug('searching compatibility in ' + search)
            mlog.debug('compiler_versions', comp_versions)

            if pkg_desc['configuration'] in search:
                comps.add('configuration')

            if desc['buildType'] in search:
                comps.add('build_type')

            if all(platform in search for platform in desc['platform']):
                comps.add('platform')

            if all(arch in search for arch in desc['architecture']):
                comps.add('arch')

            if dub_comp_id in search:
                comps.add('compiler')

            if not comp_versions or any(cv in search for cv in comp_versions):
                comps.add('compiler_version')

            if check_list.issubset(comps):
                mlog.debug('Found', target)
                return (target, comps)
            else:
                compatibilities = set.union(compatibilities, comps)

        return (None, compatibilities)

    def _cache_entries(self, pkg_desc: DubPackDesc) -> T.List[FindTargetEntry]:
        # the "old" cache is the `.dub` directory in every package of ~/.dub/packages
        dub_build_path = os.path.join(pkg_desc['path'], '.dub', 'build')

        if not os.path.exists(dub_build_path):
            mlog.warning('No such cache folder:', dub_build_path)
            return []

        mlog.debug('Checking in DUB cache folder', dub_build_path)

        return [
            {
                'search': dir_entry,
                'artifactPath': os.path.join(dub_build_path, dir_entry, pkg_desc['targetFileName'])
            }
            for dir_entry in os.listdir(dub_build_path)
        ]

    def _get_comp_versions_to_find(self, dub_comp_id: str) -> T.List[str]:
        # Get D frontend version implemented in the compiler, or the compiler version itself
        # gdc doesn't support this

        if dub_comp_id == 'gdc':
            return []

        comp_versions = [self.compiler.version]

        ret, res = self._call_compbin(['--version'])[0:2]
        if ret != 0:
            mlog.error('Failed to run', mlog.bold(' '.join(self.dubbin.get_command() + ['--version'])))
            return []
        d_ver_reg = re.search('v[0-9].[0-9][0-9][0-9].[0-9]', res)  # Ex.: v2.081.2

        if d_ver_reg is not None:
            frontend_version = d_ver_reg.group()
            frontend_id = frontend_version.rsplit('.', 1)[0].replace(
                'v', '').replace('.', '')  # Fix structure. Ex.: 2081
            comp_versions.extend([frontend_version, frontend_id])

        return comp_versions

    def _call_dubbin(self, args: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, str, str]:
        assert isinstance(self.dubbin, ExternalProgram)
        p, out, err = Popen_safe(self.dubbin.get_command() + args, env=env, cwd=self.env.get_source_dir())
        return p.returncode, out.strip(), err.strip()

    def _call_compbin(self, args: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, str, str]:
        p, out, err = Popen_safe(self.compiler.get_exelist() + args, env=env)
        return p.returncode, out.strip(), err.strip()

    def _check_dub(self) -> T.Optional[T.Tuple[ExternalProgram, str]]:

        def find() -> T.Optional[T.Tuple[ExternalProgram, str]]:
            dubbin = ExternalProgram('dub', silent=True)

            if not dubbin.found():
                return None

            try:
                p, out = Popen_safe(dubbin.get_command() + ['--version'])[0:2]
                if p.returncode != 0:
                    mlog.warning('Found dub {!r} but couldn\'t run it'
                                 ''.format(' '.join(dubbin.get_command())))
                    return None

            except (FileNotFoundError, PermissionError):
                return None

            vermatch = re.search(r'DUB version (\d+\.\d+\.\d+.*), ', out.strip())
            if vermatch:
                dubver = vermatch.group(1)
            else:
                mlog.warning(f"Found dub {' '.join(dubbin.get_command())} but couldn't parse version in {out.strip()}")
                return None

            return (dubbin, dubver)

        found = find()

        if found is None:
            mlog.log('Found DUB:', mlog.red('NO'))
        else:
            (dubbin, dubver) = found
            mlog.log('Found DUB:', mlog.bold(dubbin.get_path()),
                     '(version %s)' % dubver)

        return found
