# SPDX-License-Identifier: Apache-2.0
# Copyright 2013-2017 The Meson development team
# Copyright © 2021-2023 Intel Corporation

from __future__ import annotations

"""Dependency finders for the Qt framework."""

import abc
import re
import os
from pathlib import Path
import typing as T

from .base import DependencyException, DependencyMethods
from .configtool import ConfigToolDependency
from .detect import packages
from .framework import ExtraFrameworkDependency
from .pkgconfig import PkgConfigDependency
from .factory import DependencyFactory
from .. import mlog
from .. import mesonlib

if T.TYPE_CHECKING:
    from ..compilers import Compiler
    from ..envconfig import MachineInfo
    from ..environment import Environment
    from ..dependencies import MissingCompiler


def _qt_get_private_includes(mod_inc_dir: str, module: str, mod_version: str) -> T.List[str]:
    # 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 []

    private_dir = os.path.join(mod_inc_dir, mod_version)
    # fallback, let's try to find a directory with the latest version
    if os.path.isdir(mod_inc_dir) and 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))]

        for dirname in sorted(dirs, reverse=True):
            if len(dirname.split('.')) == 3:
                private_dir = dirname
                break
    return [private_dir, Path(private_dir, f'Qt{module}').as_posix()]


def get_qmake_host_bins(qvars: T.Dict[str, str]) -> str:
    # 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']
    return qvars['QT_INSTALL_BINS']


def get_qmake_host_libexecs(qvars: T.Dict[str, str]) -> T.Optional[str]:
    if 'QT_HOST_LIBEXECS' in qvars:
        return qvars['QT_HOST_LIBEXECS']
    return qvars.get('QT_INSTALL_LIBEXECS')


def _get_modules_lib_suffix(version: str, info: 'MachineInfo', is_debug: bool) -> str:
    """Get the module suffix based on platform and debug type."""
    suffix = ''
    if info.is_windows():
        if is_debug:
            suffix += 'd'
        if version.startswith('4'):
            suffix += '4'
    if info.is_darwin():
        if is_debug:
            suffix += '_debug'
    if mesonlib.version_compare(version, '>= 5.14.0'):
        if info.is_android():
            if info.cpu_family == 'x86':
                suffix += '_x86'
            elif info.cpu_family == 'x86_64':
                suffix += '_x86_64'
            elif info.cpu_family == 'arm':
                suffix += '_armeabi-v7a'
            elif info.cpu_family == 'aarch64':
                suffix += '_arm64-v8a'
            else:
                mlog.warning(f'Android target arch "{info.cpu_family}"" for Qt5 is unknown, '
                             'module detection may not work')
    return suffix


class QtExtraFrameworkDependency(ExtraFrameworkDependency):
    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], qvars: T.Dict[str, str], language: T.Optional[str] = None):
        super().__init__(name, env, kwargs, language=language)
        self.mod_name = name[2:]
        self.qt_extra_include_directory = qvars['QT_INSTALL_HEADERS']

    def get_compile_args(self, with_private_headers: bool = False, qt_version: str = "0") -> T.List[str]:
        if self.found():
            mod_inc_dir = os.path.join(self.framework_path, '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)]
            if self.qt_extra_include_directory:
                args += ['-I' + self.qt_extra_include_directory]
            return args
        return []


class _QtBase:

    """Mixin class for shared components between PkgConfig and Qmake."""

    link_args: T.List[str]
    clib_compiler: T.Union['MissingCompiler', 'Compiler']
    env: 'Environment'
    libexecdir: T.Optional[str] = None
    version: str

    def __init__(self, name: str, kwargs: T.Dict[str, T.Any]):
        self.name = name
        self.qtname = name.capitalize()
        self.qtver = name[-1]
        if self.qtver == "4":
            self.qtpkgname = 'Qt'
        else:
            self.qtpkgname = self.qtname

        self.private_headers = T.cast('bool', kwargs.get('private_headers', False))

        self.requested_modules = mesonlib.stringlistify(mesonlib.extract_as_list(kwargs, 'modules'))
        if not self.requested_modules:
            raise DependencyException('No ' + self.qtname + '  modules specified.')

        self.qtmain = T.cast('bool', kwargs.get('main', False))
        if not isinstance(self.qtmain, bool):
            raise DependencyException('"main" argument must be a boolean')

    def _link_with_qt_winmain(self, is_debug: bool, libdir: T.Union[str, T.List[str]]) -> bool:
        libdir = mesonlib.listify(libdir)  # TODO: shouldn't be necessary
        base_name = self.get_qt_winmain_base_name(is_debug)
        qt_winmain = self.clib_compiler.find_library(base_name, self.env, libdir)
        if qt_winmain:
            self.link_args.append(qt_winmain[0])
            return True
        return False

    def get_qt_winmain_base_name(self, is_debug: bool) -> str:
        return 'qtmaind' if is_debug else 'qtmain'

    def get_exe_args(self, compiler: 'Compiler') -> T.List[str]:
        # 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 log_details(self) -> str:
        return f'modules: {", ".join(sorted(self.requested_modules))}'


class QtPkgConfigDependency(_QtBase, PkgConfigDependency, metaclass=abc.ABCMeta):

    """Specialization of the PkgConfigDependency for Qt."""

    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
        _QtBase.__init__(self, name, kwargs)

        # Always use QtCore as the "main" dependency, since it has the extra
        # pkg-config variables that a user would expect to get. If "Core" is
        # not a requested module, delete the compile and link arguments to
        # avoid linking with something they didn't ask for
        PkgConfigDependency.__init__(self, self.qtpkgname + 'Core', env, kwargs)
        if 'Core' not in self.requested_modules:
            self.compile_args = []
            self.link_args = []

        for m in self.requested_modules:
            mod = PkgConfigDependency(self.qtpkgname + m, self.env, kwargs, language=self.language)
            if not mod.found():
                self.is_found = False
                return
            if self.private_headers:
                qt_inc_dir = mod.get_variable(pkgconfig='includedir')
                mod_private_dir = os.path.join(qt_inc_dir, 'Qt' + m)
                if not os.path.isdir(mod_private_dir):
                    # At least some versions of homebrew don't seem to set this
                    # up correctly. /usr/local/opt/qt/include/Qt + m_name is a
                    # symlink to /usr/local/opt/qt/include, but the pkg-config
                    # file points to /usr/local/Cellar/qt/x.y.z/Headers/, and
                    # the Qt + m_name there is not a symlink, it's a file
                    mod_private_dir = qt_inc_dir
                mod_private_inc = _qt_get_private_includes(mod_private_dir, m, mod.version)
                for directory in mod_private_inc:
                    mod.compile_args.append('-I' + directory)
            self._add_sub_dependency([lambda: mod])

        if self.env.machines[self.for_machine].is_windows() and self.qtmain:
            # Check if we link with debug binaries
            debug_lib_name = self.qtpkgname + 'Core' + _get_modules_lib_suffix(self.version, self.env.machines[self.for_machine], True)
            is_debug = False
            for arg in self.get_link_args():
                if arg == f'-l{debug_lib_name}' or arg.endswith(f'{debug_lib_name}.lib') or arg.endswith(f'{debug_lib_name}.a'):
                    is_debug = True
                    break
            libdir = self.get_variable(pkgconfig='libdir')
            if not self._link_with_qt_winmain(is_debug, libdir):
                self.is_found = False
                return

        self.bindir = self.get_pkgconfig_host_bins(self)
        if not self.bindir:
            # If exec_prefix is not defined, the pkg-config file is broken
            prefix = self.get_variable(pkgconfig='exec_prefix')
            if prefix:
                self.bindir = os.path.join(prefix, 'bin')

        self.libexecdir = self.get_pkgconfig_host_libexecs(self)

    @staticmethod
    @abc.abstractmethod
    def get_pkgconfig_host_bins(core: PkgConfigDependency) -> T.Optional[str]:
        pass

    @staticmethod
    @abc.abstractmethod
    def get_pkgconfig_host_libexecs(core: PkgConfigDependency) -> T.Optional[str]:
        pass

    @abc.abstractmethod
    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
        pass

    def log_info(self) -> str:
        return 'pkg-config'


class QmakeQtDependency(_QtBase, ConfigToolDependency, metaclass=abc.ABCMeta):

    """Find Qt using Qmake as a config-tool."""

    version: str
    version_arg = '-v'

    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
        _QtBase.__init__(self, name, kwargs)
        self.tool_name = f'qmake{self.qtver}'
        self.tools = [f'qmake{self.qtver}', f'qmake-{self.name}', 'qmake']

        # Add additional constraints that the Qt version is met, but preserve
        # any version requirements the user has set as well. For example, if Qt5
        # is requested, add "">= 5, < 6", but if the user has ">= 5.6", don't
        # lose that.
        kwargs = kwargs.copy()
        _vers = mesonlib.listify(kwargs.get('version', []))
        _vers.extend([f'>= {self.qtver}', f'< {int(self.qtver) + 1}'])
        kwargs['version'] = _vers

        ConfigToolDependency.__init__(self, name, env, kwargs)
        if not self.found():
            return

        # Query library path, header path, and binary path
        stdo = self.get_config_value(['-query'], 'args')
        qvars: T.Dict[str, str] = {}
        for line in stdo:
            line = line.strip()
            if line == '':
                continue
            k, v = line.split(':', 1)
            qvars[k] = v
        # Qt on macOS uses a framework, but Qt for iOS/tvOS does not
        xspec = qvars.get('QMAKE_XSPEC', '')
        if self.env.machines.host.is_darwin() and not any(s in xspec for s in ['ios', 'tvos']):
            mlog.debug("Building for macOS, looking for framework")
            self._framework_detect(qvars, self.requested_modules, kwargs)
            # Sometimes Qt is built not as a framework (for instance, when using conan pkg manager)
            # skip and fall back to normal procedure then
            if self.is_found:
                return
            else:
                mlog.debug("Building for macOS, couldn't find framework, falling back to library search")
        incdir = qvars['QT_INSTALL_HEADERS']
        self.compile_args.append('-I' + incdir)
        libdir = qvars['QT_INSTALL_LIBS']
        # Used by qt.compilers_detect()
        self.bindir = get_qmake_host_bins(qvars)
        self.libexecdir = get_qmake_host_libexecs(qvars)

        # Use the buildtype by default, but look at the b_vscrt option if the
        # compiler supports it.
        is_debug = self.env.coredata.optstore.get_value_for('buildtype') == 'debug'
        if 'b_vscrt' in self.env.coredata.optstore:
            if self.env.coredata.optstore.get_value_for('b_vscrt') in {'mdd', 'mtd'}:
                is_debug = True
        modules_lib_suffix = _get_modules_lib_suffix(self.version, self.env.machines[self.for_machine], is_debug)

        for module in self.requested_modules:
            mincdir = Path(incdir, f'Qt{module}').as_posix()
            self.compile_args.append('-I' + mincdir)

            if module == 'QuickTest':
                define_base = 'QMLTEST'
            elif module == 'Test':
                define_base = 'TESTLIB'
            else:
                define_base = module.upper()
            self.compile_args.append(f'-DQT_{define_base}_LIB')

            if self.private_headers:
                priv_inc = self.get_private_includes(mincdir, module)
                for directory in priv_inc:
                    self.compile_args.append('-I' + directory)
            libfiles = self.clib_compiler.find_library(
                self.qtpkgname + module + modules_lib_suffix, self.env,
                mesonlib.listify(libdir)) # TODO: shouldn't be necessary
            if libfiles:
                libfile = libfiles[0]
            else:
                mlog.log("Could not find:", module,
                         self.qtpkgname + module + modules_lib_suffix,
                         'in', libdir)
                self.is_found = False
                break
            self.link_args.append(libfile)

        if self.env.machines[self.for_machine].is_windows() and self.qtmain:
            if not self._link_with_qt_winmain(is_debug, libdir):
                self.is_found = False

    def _sanitize_version(self, version: str) -> str:
        m = re.search(rf'({self.qtver}(\.\d+)+)', version)
        if m:
            return m.group(0).rstrip('.')
        return version

    def get_variable_args(self, variable_name: str) -> T.List[str]:
        return ['-query', f'{variable_name}']

    @abc.abstractmethod
    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
        pass

    def _framework_detect(self, qvars: T.Dict[str, str], modules: T.List[str], kwargs: T.Dict[str, T.Any]) -> None:
        libdir = qvars['QT_INSTALL_LIBS']

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

        for m in modules:
            fname = 'Qt' + m
            mlog.debug('Looking for qt framework ' + fname)
            fwdep = QtExtraFrameworkDependency(fname, self.env, fw_kwargs, qvars, language=self.language)
            if fwdep.found():
                self.compile_args.append('-F' + libdir)
                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:
                self.is_found = False
                break
        else:
            self.is_found = True
            # Used by self.compilers_detect()
            self.bindir = get_qmake_host_bins(qvars)
            self.libexecdir = get_qmake_host_libexecs(qvars)

    def log_info(self) -> str:
        return 'qmake'


class Qt6WinMainMixin:

    def get_qt_winmain_base_name(self, is_debug: bool) -> str:
        return 'Qt6EntryPointd' if is_debug else 'Qt6EntryPoint'


class Qt4ConfigToolDependency(QmakeQtDependency):

    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
        return []


class Qt5ConfigToolDependency(QmakeQtDependency):

    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
        return _qt_get_private_includes(mod_inc_dir, module, self.version)


class Qt6ConfigToolDependency(Qt6WinMainMixin, QmakeQtDependency):

    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
        return _qt_get_private_includes(mod_inc_dir, module, self.version)


class Qt4PkgConfigDependency(QtPkgConfigDependency):

    @staticmethod
    def get_pkgconfig_host_bins(core: PkgConfigDependency) -> T.Optional[str]:
        # 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_variable(pkgconfig=f'{application}_location'))
            except mesonlib.MesonException:
                pass
        return None

    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
        return []

    @staticmethod
    def get_pkgconfig_host_libexecs(core: PkgConfigDependency) -> str:
        return None


class Qt5PkgConfigDependency(QtPkgConfigDependency):

    @staticmethod
    def get_pkgconfig_host_bins(core: PkgConfigDependency) -> str:
        return core.get_variable(pkgconfig='host_bins')

    @staticmethod
    def get_pkgconfig_host_libexecs(core: PkgConfigDependency) -> str:
        return None

    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
        return _qt_get_private_includes(mod_inc_dir, module, self.version)


class Qt6PkgConfigDependency(Qt6WinMainMixin, QtPkgConfigDependency):

    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
        super().__init__(name, env, kwargs)
        if not self.libexecdir:
            mlog.debug(f'detected Qt6 {self.version} pkg-config dependency does not '
                       'have proper tools support, ignoring')
            self.is_found = False

    @staticmethod
    def get_pkgconfig_host_bins(core: PkgConfigDependency) -> str:
        return core.get_variable(pkgconfig='bindir')

    @staticmethod
    def get_pkgconfig_host_libexecs(core: PkgConfigDependency) -> str:
        # Qt6 pkg-config for Qt defines libexecdir from 6.3+
        return core.get_variable(pkgconfig='libexecdir')

    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
        return _qt_get_private_includes(mod_inc_dir, module, self.version)


packages['qt4'] = qt4_factory = DependencyFactory(
    'qt4',
    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
    pkgconfig_class=Qt4PkgConfigDependency,
    configtool_class=Qt4ConfigToolDependency,
)

packages['qt5'] = qt5_factory = DependencyFactory(
    'qt5',
    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
    pkgconfig_class=Qt5PkgConfigDependency,
    configtool_class=Qt5ConfigToolDependency,
)

packages['qt6'] = qt6_factory = DependencyFactory(
    'qt6',
    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
    pkgconfig_class=Qt6PkgConfigDependency,
    configtool_class=Qt6ConfigToolDependency,
)
