# Copyright 2013-2021 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 .base import ExternalDependency, DependencyException, DependencyTypeName
from ..mesonlib import listify, Popen_safe, split_args, version_compare, version_compare_many
from ..programs import find_external_program
from .. import mlog
import re
import typing as T

from mesonbuild import mesonlib

if T.TYPE_CHECKING:
    from ..environment import Environment

class ConfigToolDependency(ExternalDependency):

    """Class representing dependencies found using a config tool.

    Takes the following extra keys in kwargs that it uses internally:
    :tools List[str]: A list of tool names to use
    :version_arg str: The argument to pass to the tool to get it's version
    :returncode_value int: The value of the correct returncode
        Because some tools are stupid and don't return 0
    """

    tools: T.Optional[T.List[str]] = None
    tool_name: T.Optional[str] = None
    version_arg = '--version'
    __strip_version = re.compile(r'^[0-9][0-9.]+')

    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None):
        super().__init__(DependencyTypeName('config-tool'), environment, kwargs, language=language)
        self.name = name
        # You may want to overwrite the class version in some cases
        self.tools = listify(kwargs.get('tools', self.tools))
        if not self.tool_name:
            self.tool_name = self.tools[0]
        if 'version_arg' in kwargs:
            self.version_arg = kwargs['version_arg']

        req_version_raw = kwargs.get('version', None)
        if req_version_raw is not None:
            req_version = mesonlib.stringlistify(req_version_raw)
        else:
            req_version = []
        tool, version = self.find_config(req_version, kwargs.get('returncode_value', 0))
        self.config = tool
        self.is_found = self.report_config(version, req_version)
        if not self.is_found:
            self.config = None
            return
        self.version = version

    def _sanitize_version(self, version: str) -> str:
        """Remove any non-numeric, non-point version suffixes."""
        m = self.__strip_version.match(version)
        if m:
            # Ensure that there isn't a trailing '.', such as an input like
            # `1.2.3.git-1234`
            return m.group(0).rstrip('.')
        return version

    def find_config(self, versions: T.List[str], returncode: int = 0) \
            -> T.Tuple[T.Optional[T.List[str]], T.Optional[str]]:
        """Helper method that searches for config tool binaries in PATH and
        returns the one that best matches the given version requirements.
        """
        best_match: T.Tuple[T.Optional[T.List[str]], T.Optional[str]] = (None, None)
        for potential_bin in find_external_program(
                self.env, self.for_machine, self.tool_name,
                self.tool_name, self.tools, allow_default_for_cross=False):
            if not potential_bin.found():
                continue
            tool = potential_bin.get_command()
            try:
                p, out = Popen_safe(tool + [self.version_arg])[:2]
            except (FileNotFoundError, PermissionError):
                continue
            if p.returncode != returncode:
                continue

            out = self._sanitize_version(out.strip())
            # Some tools, like pcap-config don't supply a version, but also
            # don't fail with --version, in that case just assume that there is
            # only one version and return it.
            if not out:
                return (tool, None)
            if versions:
                is_found = version_compare_many(out, versions)[0]
                # This allows returning a found version without a config tool,
                # which is useful to inform the user that you found version x,
                # but y was required.
                if not is_found:
                    tool = None
            if best_match[1]:
                if version_compare(out, '> {}'.format(best_match[1])):
                    best_match = (tool, out)
            else:
                best_match = (tool, out)

        return best_match

    def report_config(self, version: T.Optional[str], req_version: T.List[str]) -> bool:
        """Helper method to print messages about the tool."""

        found_msg: T.List[T.Union[str, mlog.AnsiDecorator]] = [mlog.bold(self.tool_name), 'found:']

        if self.config is None:
            found_msg.append(mlog.red('NO'))
            if version is not None and req_version:
                found_msg.append(f'found {version!r} but need {req_version!r}')
            elif req_version:
                found_msg.append(f'need {req_version!r}')
        else:
            found_msg += [mlog.green('YES'), '({})'.format(' '.join(self.config)), version]

        mlog.log(*found_msg)

        return self.config is not None

    def get_config_value(self, args: T.List[str], stage: str) -> T.List[str]:
        p, out, err = Popen_safe(self.config + args)
        if p.returncode != 0:
            if self.required:
                raise DependencyException(f'Could not generate {stage} for {self.name}.\n{err}')
            return []
        return split_args(out)

    def get_configtool_variable(self, variable_name: str) -> str:
        p, out, _ = Popen_safe(self.config + [f'--{variable_name}'])
        if p.returncode != 0:
            if self.required:
                raise DependencyException(
                    'Could not get variable "{}" for dependency {}'.format(
                        variable_name, self.name))
        variable = out.strip()
        mlog.debug(f'Got config-tool variable {variable_name} : {variable}')
        return variable

    def log_tried(self) -> str:
        return self.type_name

    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
                     configtool: T.Optional[str] = None, internal: T.Optional[str] = None,
                     default_value: T.Optional[str] = None,
                     pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
        if configtool:
            # In the not required case '' (empty string) will be returned if the
            # variable is not found. Since '' is a valid value to return we
            # set required to True here to force and error, and use the
            # finally clause to ensure it's restored.
            restore = self.required
            self.required = True
            try:
                return self.get_configtool_variable(configtool)
            except DependencyException:
                pass
            finally:
                self.required = restore
        if default_value is not None:
            return default_value
        raise DependencyException(f'Could not get config-tool variable and no default provided for {self!r}')
