# Copyright 2013-2019 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.

# This file contains the detection logic for miscellaneous external dependencies.

import functools
import os
import re
import shutil
import subprocess
from pathlib import Path

from ..mesonlib import OrderedSet, join_args
from .base import DependencyException, DependencyMethods
from .configtool import ConfigToolDependency
from .pkgconfig import PkgConfigDependency
from .factory import factory_methods
import typing as T

if T.TYPE_CHECKING:
    from .base import Dependency
    from .factory import DependencyGenerator
    from ..environment import Environment
    from ..mesonlib import MachineChoice


class HDF5PkgConfigDependency(PkgConfigDependency):

    """Handle brokenness in the HDF5 pkg-config files."""

    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
        language = language or 'c'
        if language not in {'c', 'cpp', 'fortran'}:
            raise DependencyException(f'Language {language} is not supported with HDF5.')

        super().__init__(name, environment, kwargs, language)
        if not self.is_found:
            return

        # some broken pkgconfig don't actually list the full path to the needed includes
        newinc = []  # type: T.List[str]
        for arg in self.compile_args:
            if arg.startswith('-I'):
                stem = 'static' if kwargs.get('static', False) else 'shared'
                if (Path(arg[2:]) / stem).is_dir():
                    newinc.append('-I' + str(Path(arg[2:]) / stem))
        self.compile_args += newinc

        link_args = []  # type: T.List[str]
        for larg in self.get_link_args():
            lpath = Path(larg)
            # some pkg-config hdf5.pc (e.g. Ubuntu) don't include the commonly-used HL HDF5 libraries,
            # so let's add them if they exist
            # additionally, some pkgconfig HDF5 HL files are malformed so let's be sure to find HL anyway
            if lpath.is_file():
                hl = []
                if language == 'cpp':
                    hl += ['_hl_cpp', '_cpp']
                elif language == 'fortran':
                    hl += ['_hl_fortran', 'hl_fortran', '_fortran']
                hl += ['_hl']  # C HL library, always needed

                suffix = '.' + lpath.name.split('.', 1)[1]  # in case of .dll.a
                for h in hl:
                    hlfn = lpath.parent / (lpath.name.split('.', 1)[0] + h + suffix)
                    if hlfn.is_file():
                        link_args.append(str(hlfn))
                # HDF5 C libs are required by other HDF5 languages
                link_args.append(larg)
            else:
                link_args.append(larg)

        self.link_args = link_args


class HDF5ConfigToolDependency(ConfigToolDependency):

    """Wrapper around hdf5 binary config tools."""

    version_arg = '-showconfig'

    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
        language = language or 'c'
        if language not in {'c', 'cpp', 'fortran'}:
            raise DependencyException(f'Language {language} is not supported with HDF5.')

        if language == 'c':
            cenv = 'CC'
            tools = ['h5cc']
        elif language == 'cpp':
            cenv = 'CXX'
            tools = ['h5c++']
        elif language == 'fortran':
            cenv = 'FC'
            tools = ['h5fc']
        else:
            raise DependencyException('How did you get here?')

        # We need this before we call super()
        for_machine = self.get_for_machine_from_kwargs(kwargs)

        nkwargs = kwargs.copy()
        nkwargs['tools'] = tools

        # Override the compiler that the config tools are going to use by
        # setting the environment variables that they use for the compiler and
        # linkers.
        compiler = environment.coredata.compilers[for_machine][language]
        try:
            os.environ[f'HDF5_{cenv}'] = join_args(compiler.get_exelist())
            os.environ[f'HDF5_{cenv}LINKER'] = join_args(compiler.get_linker_exelist())
            super().__init__(name, environment, nkwargs, language)
        finally:
            del os.environ[f'HDF5_{cenv}']
            del os.environ[f'HDF5_{cenv}LINKER']
        if not self.is_found:
            return

        # We first need to call the tool with -c to get the compile arguments
        # and then without -c to get the link arguments.
        args = self.get_config_value(['-show', '-c'], 'args')[1:]
        args += self.get_config_value(['-show', '-noshlib' if kwargs.get('static', False) else '-shlib'], 'args')[1:]
        for arg in args:
            if arg.startswith(('-I', '-f', '-D')) or arg == '-pthread':
                self.compile_args.append(arg)
            elif arg.startswith(('-L', '-l', '-Wl')):
                self.link_args.append(arg)
            elif Path(arg).is_file():
                self.link_args.append(arg)

        # If the language is not C we need to add C as a subdependency
        if language != 'c':
            nkwargs = kwargs.copy()
            nkwargs['language'] = 'c'
            # I'm being too clever for mypy and pylint
            self.is_found = self._add_sub_dependency(hdf5_factory(environment, for_machine, nkwargs))  # pylint: disable=no-value-for-parameter

    def _sanitize_version(self, ver: str) -> str:
        v = re.search(r'\s*HDF5 Version: (\d+\.\d+\.\d+)', ver)
        return v.group(1)


@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL})
def hdf5_factory(env: 'Environment', for_machine: 'MachineChoice',
                 kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
    language = kwargs.get('language')
    candidates: T.List['DependencyGenerator'] = []

    if DependencyMethods.PKGCONFIG in methods:
        # Use an ordered set so that these remain the first tried pkg-config files
        pkgconfig_files = OrderedSet(['hdf5', 'hdf5-serial'])
        # FIXME: This won't honor pkg-config paths, and cross-native files
        PCEXE = shutil.which('pkg-config')
        if PCEXE:
            # some distros put hdf5-1.2.3.pc with version number in .pc filename.
            ret = subprocess.run([PCEXE, '--list-all'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
                                    universal_newlines=True)
            if ret.returncode == 0:
                for pkg in ret.stdout.split('\n'):
                    if pkg.startswith('hdf5'):
                        pkgconfig_files.add(pkg.split(' ', 1)[0])

        for pkg in pkgconfig_files:
            candidates.append(functools.partial(HDF5PkgConfigDependency, pkg, env, kwargs, language))

    if DependencyMethods.CONFIG_TOOL in methods:
        candidates.append(functools.partial(HDF5ConfigToolDependency, 'hdf5', env, kwargs, language))

    return candidates
