# Copyright 2013-2017 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 external dependencies that
# are UI-related.

import os
import re
import subprocess
from collections import OrderedDict

from .. import mlog
from .. import mesonlib
from ..mesonlib import (
    MesonException, Popen_safe, extract_as_list, for_windows, for_cygwin,
    version_compare_many
)
from ..environment import detect_cpu

from .base import DependencyException, DependencyMethods
from .base import ExternalDependency, ExternalProgram
from .base import ExtraFrameworkDependency, PkgConfigDependency
from .base import ConfigToolDependency

from ..interpreterbase import FeatureNew

class GLDependency(ExternalDependency):
    def __init__(self, environment, kwargs):
        super().__init__('gl', environment, None, kwargs)
        if DependencyMethods.SYSTEM in self.methods:
            if mesonlib.is_osx():
                self.is_found = True
                # FIXME: Use AppleFrameworks dependency
                self.link_args = ['-framework', 'OpenGL']
                # FIXME: Detect version using self.compiler
                self.version = '1'
                return
            if mesonlib.is_windows():
                self.is_found = True
                # FIXME: Use self.compiler.find_library()
                self.link_args = ['-lopengl32']
                # FIXME: Detect version using self.compiler
                self.version = '1'
                return

    @classmethod
    def _factory(cls, environment, kwargs):
        if DependencyMethods.PKGCONFIG in cls._process_method_kw(kwargs):
            try:
                pcdep = PkgConfigDependency('gl', environment, kwargs)
                if pcdep.found():
                    return pcdep
            except Exception:
                pass
        return GLDependency(environment, kwargs)

    @staticmethod
    def get_methods():
        if mesonlib.is_osx() or mesonlib.is_windows():
            return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM]
        else:
            return [DependencyMethods.PKGCONFIG]


class GnuStepDependency(ConfigToolDependency):

    tools = ['gnustep-config']
    tool_name = 'gnustep-config'

    def __init__(self, environment, kwargs):
        super().__init__('gnustep', environment, 'objc', kwargs)
        if not self.is_found:
            return
        self.modules = kwargs.get('modules', [])
        self.compile_args = self.filter_args(
            self.get_config_value(['--objc-flags'], 'compile_args'))
        self.link_args = self.weird_filter(self.get_config_value(
            ['--gui-libs' if 'gui' in self.modules else '--base-libs'],
            'link_args'))

    def find_config(self, versions=None):
        tool = self.tools[0]
        try:
            p, out = Popen_safe([tool, '--help'])[:2]
        except (FileNotFoundError, PermissionError):
            return (None, None)
        if p.returncode != 0:
            return (None, None)
        self.config = tool
        found_version = self.detect_version()
        if versions and not version_compare_many(found_version, versions)[0]:
            return (None, found_version)

        return (tool, found_version)

    def weird_filter(self, elems):
        """When building packages, the output of the enclosing Make is
        sometimes mixed among the subprocess output. I have no idea why. As a
        hack filter out everything that is not a flag.
        """
        return [e for e in elems if e.startswith('-')]

    def filter_args(self, args):
        """gnustep-config returns a bunch of garbage args such as -O2 and so
        on. Drop everything that is not needed.
        """
        result = []
        for f in args:
            if f.startswith('-D') \
                    or f.startswith('-f') \
                    or f.startswith('-I') \
                    or f == '-pthread' \
                    or (f.startswith('-W') and not f == '-Wall'):
                result.append(f)
        return result

    def detect_version(self):
        gmake = self.get_config_value(['--variable=GNUMAKE'], 'variable')[0]
        makefile_dir = self.get_config_value(['--variable=GNUSTEP_MAKEFILES'], 'variable')[0]
        # This Makefile has the GNUStep version set
        base_make = os.path.join(makefile_dir, 'Additional', 'base.make')
        # Print the Makefile variable passed as the argument. For instance, if
        # you run the make target `print-SOME_VARIABLE`, this will print the
        # value of the variable `SOME_VARIABLE`.
        printver = "print-%:\n\t@echo '$($*)'"
        env = os.environ.copy()
        # See base.make to understand why this is set
        env['FOUNDATION_LIB'] = 'gnu'
        p, o, e = Popen_safe([gmake, '-f', '-', '-f', base_make,
                              'print-GNUSTEP_BASE_VERSION'],
                             env=env, write=printver, stdin=subprocess.PIPE)
        version = o.strip()
        if not version:
            mlog.debug("Couldn't detect GNUStep version, falling back to '1'")
            # Fallback to setting some 1.x version
            version = '1'
        return version


def _qt_get_private_includes(mod_inc_dir, module, mod_version):
    # usually Qt5 puts private headers in /QT_INSTALL_HEADERS/module/VERSION/module/private
    # except for at least QtWebkit and Enginio where the module version doesn't match Qt version
    # as an example with Qt 5.10.1 on linux you would get:
    # /usr/include/qt5/QtCore/5.10.1/QtCore/private/
    # /usr/include/qt5/QtWidgets/5.10.1/QtWidgets/private/
    # /usr/include/qt5/QtWebKit/5.212.0/QtWebKit/private/

    # on Qt4 when available private folder is directly in module folder
    # like /usr/include/QtCore/private/
    if int(mod_version.split('.')[0]) < 5:
        return tuple()

    private_dir = os.path.join(mod_inc_dir, mod_version)
    # fallback, let's try to find a directory with the latest version
    if not os.path.exists(private_dir):
        dirs = [filename for filename in os.listdir(mod_inc_dir)
                if os.path.isdir(os.path.join(mod_inc_dir, filename))]
        dirs.sort(reverse=True)

        for dirname in dirs:
            if len(dirname.split('.')) == 3:
                private_dir = dirname
                break
    return (private_dir,
            os.path.join(private_dir, 'Qt' + module))

class QtExtraFrameworkDependency(ExtraFrameworkDependency):
    def __init__(self, name, required, path, env, lang, kwargs):
        super().__init__(name, required, path, env, lang, kwargs)
        self.mod_name = name[2:]

    def get_compile_args(self, with_private_headers=False, qt_version="0"):
        if self.found():
            mod_inc_dir = os.path.join(self.path, self.name, 'Headers')
            args = ['-I' + mod_inc_dir]
            if with_private_headers:
                args += ['-I' + dirname for dirname in _qt_get_private_includes(mod_inc_dir, self.mod_name, qt_version)]
            return args
        return []

class QtBaseDependency(ExternalDependency):
    def __init__(self, name, env, kwargs):
        super().__init__(name, env, 'cpp', kwargs)
        self.qtname = name.capitalize()
        self.qtver = name[-1]
        if self.qtver == "4":
            self.qtpkgname = 'Qt'
        else:
            self.qtpkgname = self.qtname
        self.root = '/usr'
        self.bindir = None
        self.private_headers = kwargs.get('private_headers', False)
        mods = extract_as_list(kwargs, 'modules')
        if not mods:
            raise DependencyException('No ' + self.qtname + '  modules specified.')
        type_text = 'cross' if env.is_cross_build() else 'native'
        found_msg = '{} {} {{}} dependency (modules: {}) found:' \
                    ''.format(self.qtname, type_text, ', '.join(mods))
        from_text = 'pkg-config'

        # Keep track of the detection methods used, for logging purposes.
        methods = []
        # Prefer pkg-config, then fallback to `qmake -query`
        if DependencyMethods.PKGCONFIG in self.methods:
            self._pkgconfig_detect(mods, kwargs)
            methods.append('pkgconfig')
        if not self.is_found and DependencyMethods.QMAKE in self.methods:
            from_text = self._qmake_detect(mods, kwargs)
            methods.append('qmake-' + self.name)
            methods.append('qmake')
        if not self.is_found:
            # Reset compile args and link args
            self.compile_args = []
            self.link_args = []
            from_text = '(checked {})'.format(mlog.format_list(methods))
            self.version = 'none'
            if self.required:
                err_msg = '{} {} dependency not found {}' \
                          ''.format(self.qtname, type_text, from_text)
                raise DependencyException(err_msg)
            if not self.silent:
                mlog.log(found_msg.format(from_text), mlog.red('NO'))
            return
        from_text = '`{}`'.format(from_text)
        if not self.silent:
            mlog.log(found_msg.format(from_text), mlog.green('YES'))

    def compilers_detect(self):
        "Detect Qt (4 or 5) moc, uic, rcc in the specified bindir or in PATH"
        if self.bindir or for_windows(self.env.is_cross_build(), self.env):
            moc = ExternalProgram(os.path.join(self.bindir, 'moc'), silent=True)
            uic = ExternalProgram(os.path.join(self.bindir, 'uic'), silent=True)
            rcc = ExternalProgram(os.path.join(self.bindir, 'rcc'), silent=True)
            lrelease = ExternalProgram(os.path.join(self.bindir, 'lrelease'), silent=True)
        else:
            # We don't accept unsuffixed 'moc', 'uic', and 'rcc' because they
            # are sometimes older, or newer versions.
            moc = ExternalProgram('moc-' + self.name, silent=True)
            uic = ExternalProgram('uic-' + self.name, silent=True)
            rcc = ExternalProgram('rcc-' + self.name, silent=True)
            lrelease = ExternalProgram('lrelease-' + self.name, silent=True)
        return moc, uic, rcc, lrelease

    def _pkgconfig_detect(self, mods, kwargs):
        # We set the value of required to False so that we can try the
        # qmake-based fallback if pkg-config fails.
        kwargs['required'] = False
        modules = OrderedDict()
        for module in mods:
            modules[module] = PkgConfigDependency(self.qtpkgname + module, self.env,
                                                  kwargs, language=self.language)
        for m_name, m in modules.items():
            if not m.found():
                self.is_found = False
                return
            self.compile_args += m.get_compile_args()
            if self.private_headers:
                qt_inc_dir = m.get_pkgconfig_variable('includedir', dict())
                mod_private_inc = _qt_get_private_includes(os.path.join(qt_inc_dir, 'Qt' + m_name), m_name, m.version)
                for dir in mod_private_inc:
                    self.compile_args.append('-I' + dir)
            self.link_args += m.get_link_args()
        self.is_found = True
        self.version = m.version
        self.pcdep = list(modules.values())
        # Try to detect moc, uic, rcc
        if 'Core' in modules:
            core = modules['Core']
        else:
            corekwargs = {'required': 'false', 'silent': 'true'}
            core = PkgConfigDependency(self.qtpkgname + 'Core', self.env, corekwargs,
                                       language=self.language)
            self.pcdep.append(core)
        # Used by self.compilers_detect()
        self.bindir = self.get_pkgconfig_host_bins(core)
        if not self.bindir:
            # If exec_prefix is not defined, the pkg-config file is broken
            prefix = core.get_pkgconfig_variable('exec_prefix', {})
            if prefix:
                self.bindir = os.path.join(prefix, 'bin')

    def _find_qmake(self, qmake):
        # Even when cross-compiling, if we don't get a cross-info qmake, we
        # fallback to using the qmake in PATH because that's what we used to do
        if self.env.is_cross_build():
            qmake = self.env.cross_info.config['binaries'].get('qmake', qmake)
        return ExternalProgram(qmake, silent=True)

    def _qmake_detect(self, mods, kwargs):
        for qmake in ('qmake-' + self.name, 'qmake'):
            self.qmake = self._find_qmake(qmake)
            if not self.qmake.found():
                continue
            # Check that the qmake is for qt5
            pc, stdo = Popen_safe(self.qmake.get_command() + ['-v'])[0:2]
            if pc.returncode != 0:
                continue
            if not 'Qt version ' + self.qtver in stdo:
                mlog.log('QMake is not for ' + self.qtname)
                continue
            # Found qmake for Qt5!
            break
        else:
            # Didn't find qmake :(
            self.is_found = False
            return
        self.version = re.search(self.qtver + '(\.\d+)+', stdo).group(0)
        # Query library path, header path, and binary path
        mlog.log("Found qmake:", mlog.bold(self.qmake.get_name()), '(%s)' % self.version)
        stdo = Popen_safe(self.qmake.get_command() + ['-query'])[1]
        qvars = {}
        for line in stdo.split('\n'):
            line = line.strip()
            if line == '':
                continue
            (k, v) = tuple(line.split(':', 1))
            qvars[k] = v
        if mesonlib.is_osx():
            self._framework_detect(qvars, mods, kwargs)
            return qmake
        incdir = qvars['QT_INSTALL_HEADERS']
        self.compile_args.append('-I' + incdir)
        libdir = qvars['QT_INSTALL_LIBS']
        if for_cygwin(self.env.is_cross_build(), self.env):
            shlibext = '.dll.a'
        else:
            shlibext = '.so'
        # Used by self.compilers_detect()
        self.bindir = self.get_qmake_host_bins(qvars)
        self.is_found = True
        for module in mods:
            mincdir = os.path.join(incdir, 'Qt' + module)
            self.compile_args.append('-I' + mincdir)
            if self.private_headers:
                priv_inc = self.get_private_includes(mincdir, module)
                for dir in priv_inc:
                    self.compile_args.append('-I' + dir)
            if for_windows(self.env.is_cross_build(), self.env):
                is_debug = self.env.coredata.get_builtin_option('buildtype') == 'debug'
                dbg = 'd' if is_debug else ''
                if self.qtver == '4':
                    base_name = 'Qt' + module + dbg + '4'
                else:
                    base_name = 'Qt5' + module + dbg
                libfile = os.path.join(libdir, base_name + '.lib')
                if not os.path.isfile(libfile):
                    # MinGW can link directly to .dll
                    libfile = os.path.join(self.bindir, base_name + '.dll')
                    if not os.path.isfile(libfile):
                        self.is_found = False
                        break
            else:
                libfile = os.path.join(libdir, 'lib{}{}{}'.format(self.qtpkgname, module, shlibext))
                if not os.path.isfile(libfile):
                    self.is_found = False
                    break
            self.link_args.append(libfile)
        return qmake

    def _framework_detect(self, qvars, modules, kwargs):
        libdir = qvars['QT_INSTALL_LIBS']

        # ExtraFrameworkDependency doesn't support any methods
        fw_kwargs = kwargs.copy()
        fw_kwargs.pop('method', None)

        for m in modules:
            fname = 'Qt' + m
            fwdep = QtExtraFrameworkDependency(fname, False, libdir, self.env,
                                               self.language, fw_kwargs)
            self.compile_args.append('-F' + libdir)
            if fwdep.found():
                self.compile_args += fwdep.get_compile_args(with_private_headers=self.private_headers,
                                                            qt_version=self.version)
                self.link_args += fwdep.get_link_args()
            else:
                break
        else:
            self.is_found = True
        # Used by self.compilers_detect()
        self.bindir = self.get_qmake_host_bins(qvars)

    def get_qmake_host_bins(self, qvars):
        # Prefer QT_HOST_BINS (qt5, correct for cross and native compiling)
        # but fall back to QT_INSTALL_BINS (qt4)
        if 'QT_HOST_BINS' in qvars:
            return qvars['QT_HOST_BINS']
        else:
            return qvars['QT_INSTALL_BINS']

    @staticmethod
    def get_methods():
        return [DependencyMethods.PKGCONFIG, DependencyMethods.QMAKE]

    def get_exe_args(self, compiler):
        # Originally this was -fPIE but nowadays the default
        # for upstream and distros seems to be -reduce-relocations
        # which requires -fPIC. This may cause a performance
        # penalty when using self-built Qt or on platforms
        # where -fPIC is not required. If this is an issue
        # for you, patches are welcome.
        return compiler.get_pic_args()

    def get_private_includes(self, mod_inc_dir, module):
        return tuple()


class Qt4Dependency(QtBaseDependency):
    def __init__(self, env, kwargs):
        QtBaseDependency.__init__(self, 'qt4', env, kwargs)

    def get_pkgconfig_host_bins(self, core):
        # Only return one bins dir, because the tools are generally all in one
        # directory for Qt4, in Qt5, they must all be in one directory. Return
        # the first one found among the bin variables, in case one tool is not
        # configured to be built.
        applications = ['moc', 'uic', 'rcc', 'lupdate', 'lrelease']
        for application in applications:
            try:
                return os.path.dirname(core.get_pkgconfig_variable('%s_location' % application, {}))
            except MesonException:
                pass


class Qt5Dependency(QtBaseDependency):
    def __init__(self, env, kwargs):
        QtBaseDependency.__init__(self, 'qt5', env, kwargs)

    def get_pkgconfig_host_bins(self, core):
        return core.get_pkgconfig_variable('host_bins', {})

    def get_private_includes(self, mod_inc_dir, module):
        return _qt_get_private_includes(mod_inc_dir, module, self.version)


# There are three different ways of depending on SDL2:
# sdl2-config, pkg-config and OSX framework
class SDL2Dependency(ExternalDependency):
    def __init__(self, environment, kwargs):
        super().__init__('sdl2', environment, None, kwargs)

    @classmethod
    def _factory(cls, environment, kwargs):
        methods = cls._process_method_kw(kwargs)
        if DependencyMethods.PKGCONFIG in methods:
            try:
                pcdep = PkgConfigDependency('sdl2', environment, kwargs)
                if pcdep.found():
                    return pcdep
            except Exception as e:
                mlog.debug('SDL 2 not found via pkgconfig. Trying next, error was:', str(e))
        if DependencyMethods.CONFIG_TOOL in methods:
            try:
                ctdep = ConfigToolDependency.factory(
                    'sdl2', environment, None, kwargs, ['sdl2-config'], 'sdl2-config')
                if ctdep.found():
                    ctdep.compile_args = ctdep.get_config_value(['--cflags'], 'compile_args')
                    ctdep.link_args = ctdep.get_config_value(['--libs'], 'link_args')
                    return ctdep
            except Exception as e:
                mlog.debug('SDL 2 not found via sdl2-config. Trying next, error was:', str(e))
        if DependencyMethods.EXTRAFRAMEWORK in methods:
            if mesonlib.is_osx():
                fwdep = ExtraFrameworkDependency('sdl2', False, None, environment,
                                                 kwargs.get('language', None), kwargs)
                if fwdep.found():
                    fwdep.version = '2'  # FIXME
                    return fwdep
            mlog.log('Dependency', mlog.bold('sdl2'), 'found:', mlog.red('NO'))

        return SDL2Dependency(environment, kwargs)

    @staticmethod
    def get_methods():
        if mesonlib.is_osx():
            return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK]
        else:
            return [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL]


class WxDependency(ConfigToolDependency):

    tools = ['wx-config-3.0', 'wx-config']
    tool_name = 'wx-config'

    def __init__(self, environment, kwargs):
        super().__init__('WxWidgets', environment, None, kwargs)
        if not self.is_found:
            return
        self.requested_modules = self.get_requested(kwargs)
        # wx-config seems to have a cflags as well but since it requires C++,
        # this should be good, at least for now.
        self.compile_args = self.get_config_value(['--cxxflags'] + self.requested_modules, 'compile_args')
        self.link_args = self.get_config_value(['--libs'] + self.requested_modules, 'link_args')

    def get_requested(self, kwargs):
        if 'modules' not in kwargs:
            return []
        candidates = extract_as_list(kwargs, 'modules')
        for c in candidates:
            if not isinstance(c, str):
                raise DependencyException('wxwidgets module argument is not a string')
        return candidates


class VulkanDependency(ExternalDependency):

    @FeatureNew('Vulkan Dependency', '0.42.0')
    def __init__(self, environment, kwargs):
        super().__init__('vulkan', environment, None, kwargs)

        if DependencyMethods.SYSTEM in self.methods:
            try:
                self.vulkan_sdk = os.environ['VULKAN_SDK']
                if not os.path.isabs(self.vulkan_sdk):
                    raise DependencyException('VULKAN_SDK must be an absolute path.')
            except KeyError:
                self.vulkan_sdk = None

            if self.vulkan_sdk:
                # TODO: this config might not work on some platforms, fix bugs as reported
                # we should at least detect other 64-bit platforms (e.g. armv8)
                lib_name = 'vulkan'
                if mesonlib.is_windows():
                    lib_name = 'vulkan-1'
                    lib_dir = 'Lib32'
                    inc_dir = 'Include'
                    if detect_cpu({}) == 'x86_64':
                        lib_dir = 'Lib'
                else:
                    lib_name = 'vulkan'
                    lib_dir = 'lib'
                    inc_dir = 'include'

                # make sure header and lib are valid
                inc_path = os.path.join(self.vulkan_sdk, inc_dir)
                header = os.path.join(inc_path, 'vulkan', 'vulkan.h')
                lib_path = os.path.join(self.vulkan_sdk, lib_dir)
                find_lib = self.compiler.find_library(lib_name, environment, lib_path)

                if not find_lib:
                    raise DependencyException('VULKAN_SDK point to invalid directory (no lib)')

                if not os.path.isfile(header):
                    raise DependencyException('VULKAN_SDK point to invalid directory (no include)')

                self.type_name = 'vulkan_sdk'
                self.is_found = True
                self.compile_args.append('-I' + inc_path)
                self.link_args.append('-L' + lib_path)
                self.link_args.append('-l' + lib_name)

                # TODO: find a way to retrieve the version from the sdk?
                # Usually it is a part of the path to it (but does not have to be)
                self.version = '1'
                return
            else:
                # simply try to guess it, usually works on linux
                libs = self.compiler.find_library('vulkan', environment, [])
                if libs is not None and self.compiler.has_header('vulkan/vulkan.h', '', environment):
                    self.type_name = 'system'
                    self.is_found = True
                    self.version = 1 # TODO
                    for lib in libs:
                        self.link_args.append(lib)
                    return

    @classmethod
    def _factory(cls, environment, kwargs):
        if DependencyMethods.PKGCONFIG in cls._process_method_kw(kwargs):
            try:
                pcdep = PkgConfigDependency('vulkan', environment, kwargs)
                if pcdep.found():
                    return pcdep
            except Exception:
                pass

        return VulkanDependency(environment, kwargs)

    @staticmethod
    def get_methods():
        return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM]
