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

from pathlib import Path
import functools
import os
import typing as T

from ..mesonlib import OptionKey
from .base import DependencyMethods
from .base import DependencyException
from .cmake import CMakeDependency
from .pkgconfig import PkgConfigDependency
from .factory import factory_methods

if T.TYPE_CHECKING:
    from ..environment import Environment, MachineChoice
    from .factory import DependencyGenerator


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

    if DependencyMethods.PKGCONFIG in methods:
        static_opt = kwargs.get('static', env.coredata.get_option(OptionKey('prefer_static')))
        mkl = 'mkl-static-lp64-iomp' if static_opt else 'mkl-dynamic-lp64-iomp'
        candidates.append(functools.partial(
            MKLPkgConfigDependency, mkl, env, kwargs))

        for pkg in ['scalapack-openmpi', 'scalapack']:
            candidates.append(functools.partial(
                PkgConfigDependency, pkg, env, kwargs))

    if DependencyMethods.CMAKE in methods:
        candidates.append(functools.partial(
            CMakeDependency, 'Scalapack', env, kwargs))

    return candidates


class MKLPkgConfigDependency(PkgConfigDependency):

    """PkgConfigDependency for Intel MKL.

    MKL's pkg-config is pretty much borked in every way. We need to apply a
    bunch of fixups to make it work correctly.
    """

    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
                 language: T.Optional[str] = None):
        _m = os.environ.get('MKLROOT')
        self.__mklroot = Path(_m).resolve() if _m else None

        # We need to call down into the normal super() method even if we don't
        # find mklroot, otherwise we won't have all of the instance variables
        # initialized that meson expects.
        super().__init__(name, env, kwargs, language=language)

        # Doesn't work with gcc on windows, but does on Linux
        if (not self.__mklroot or (env.machines[self.for_machine].is_windows()
                                   and self.clib_compiler.id == 'gcc')):
            self.is_found = False

        # This can happen either because we're using GCC, we couldn't find the
        # mklroot, or the pkg-config couldn't find it.
        if not self.is_found:
            return

        assert self.version != '', 'This should not happen if we didn\'t return above'

        if self.version == 'unknown':
            # At least by 2020 the version is in the pkg-config, just not with
            # the correct name
            v = self.get_variable(pkgconfig='Version', default_value='')

            if not v and self.__mklroot:
                try:
                    v = (
                        self.__mklroot.as_posix()
                        .split('compilers_and_libraries_')[1]
                        .split('/', 1)[0]
                    )
                except IndexError:
                    pass

            if v:
                assert isinstance(v, str)
                self.version = v

    def _set_libs(self) -> None:
        super()._set_libs()

        if self.env.machines[self.for_machine].is_windows():
            suffix = '.lib'
        elif self.static:
            suffix = '.a'
        else:
            suffix = ''
        libdir = self.__mklroot / 'lib/intel64'

        if self.clib_compiler.id == 'gcc':
            for i, a in enumerate(self.link_args):
                # only replace in filename, not in directory names
                dirname, basename = os.path.split(a)
                if 'mkl_intel_lp64' in basename:
                    basename = basename.replace('intel', 'gf')
                    self.link_args[i] = '/' + os.path.join(dirname, basename)
        # MKL pkg-config omits scalapack
        # be sure "-L" and "-Wl" are first if present
        i = 0
        for j, a in enumerate(self.link_args):
            if a.startswith(('-L', '-Wl')):
                i = j + 1
            elif j > 3:
                break
        if self.env.machines[self.for_machine].is_windows() or self.static:
            self.link_args.insert(
                i, str(libdir / ('mkl_scalapack_lp64' + suffix))
            )
            self.link_args.insert(
                i + 1, str(libdir / ('mkl_blacs_intelmpi_lp64' + suffix))
            )
        else:
            self.link_args.insert(i, '-lmkl_scalapack_lp64')
            self.link_args.insert(i + 1, '-lmkl_blacs_intelmpi_lp64')

    def _set_cargs(self) -> None:
        env = None
        if self.language == 'fortran':
            # gfortran doesn't appear to look in system paths for INCLUDE files,
            # so don't allow pkg-config to suppress -I flags for system paths
            env = os.environ.copy()
            env['PKG_CONFIG_ALLOW_SYSTEM_CFLAGS'] = '1'
        ret, out, err = self._call_pkgbin([
            '--cflags', self.name,
            '--define-variable=prefix=' + self.__mklroot.as_posix()],
            env=env)
        if ret != 0:
            raise DependencyException('Could not generate cargs for %s:\n%s\n' %
                                      (self.name, err))
        self.compile_args = self._convert_mingw_paths(self._split_args(out))
