# SPDX-License-Identifier: Apache-2.0
# Copyright 2012-2022 The Meson development team

"""
Contains the strict minimum to run scripts.

When the backend needs to call back into Meson during compilation for running
scripts or wrapping commands, it is important to load as little python modules
as possible for performance reasons.
"""

from __future__ import annotations
from dataclasses import dataclass
import os
import abc
import typing as T

if T.TYPE_CHECKING:
    from hashlib import _Hash
    from typing_extensions import Literal
    from ..mparser import BaseNode
    from .. import programs

    EnvironOrDict = T.Union[T.Dict[str, str], os._Environ[str]]

    EnvInitValueType = T.Dict[str, T.Union[str, T.List[str]]]


class MesonException(Exception):
    '''Exceptions thrown by Meson'''

    def __init__(self, *args: object, file: T.Optional[str] = None,
                 lineno: T.Optional[int] = None, colno: T.Optional[int] = None):
        super().__init__(*args)
        self.file = file
        self.lineno = lineno
        self.colno = colno

    @classmethod
    def from_node(cls, *args: object, node: BaseNode) -> MesonException:
        """Create a MesonException with location data from a BaseNode

        :param node: A BaseNode to set location data from
        :return: A Meson Exception instance
        """
        return cls(*args, file=node.filename, lineno=node.lineno, colno=node.colno)

class MesonBugException(MesonException):
    '''Exceptions thrown when there is a clear Meson bug that should be reported'''

    def __init__(self, msg: str, file: T.Optional[str] = None,
                 lineno: T.Optional[int] = None, colno: T.Optional[int] = None):
        super().__init__(msg + '\n\n    This is a Meson bug and should be reported!',
                         file=file, lineno=lineno, colno=colno)

class HoldableObject(metaclass=abc.ABCMeta):
    ''' Dummy base class for all objects that can be
        held by an interpreter.baseobjects.ObjectHolder '''

class EnvironmentVariables(HoldableObject):
    def __init__(self, values: T.Optional[EnvInitValueType] = None,
                 init_method: Literal['set', 'prepend', 'append'] = 'set', separator: str = os.pathsep) -> None:
        self.envvars: T.List[T.Tuple[T.Callable[[T.Dict[str, str], str, T.List[str], str, T.Optional[str]], str], str, T.List[str], str]] = []
        # The set of all env vars we have operations for. Only used for self.has_name()
        self.varnames: T.Set[str] = set()
        self.unset_vars: T.Set[str] = set()

        if values:
            init_func = getattr(self, init_method)
            for name, value in values.items():
                v = value if isinstance(value, list) else [value]
                init_func(name, v, separator)

    def __repr__(self) -> str:
        repr_str = "<{0}: {1}>"
        return repr_str.format(self.__class__.__name__, self.envvars)

    def hash(self, hasher: _Hash) -> None:
        myenv = self.get_env({})
        for key in sorted(myenv.keys()):
            hasher.update(bytes(key, encoding='utf-8'))
            hasher.update(b',')
            hasher.update(bytes(myenv[key], encoding='utf-8'))
            hasher.update(b';')

    def has_name(self, name: str) -> bool:
        return name in self.varnames

    def get_names(self) -> T.Set[str]:
        return self.varnames

    def merge(self, other: EnvironmentVariables) -> None:
        for method, name, values, separator in other.envvars:
            self.varnames.add(name)
            self.envvars.append((method, name, values, separator))
            if name in self.unset_vars:
                self.unset_vars.remove(name)
        self.unset_vars.update(other.unset_vars)

    def set(self, name: str, values: T.List[str], separator: str = os.pathsep) -> None:
        if name in self.unset_vars:
            raise MesonException(f'You cannot set the already unset variable {name!r}')
        self.varnames.add(name)
        self.envvars.append((self._set, name, values, separator))

    def unset(self, name: str) -> None:
        if name in self.varnames:
            raise MesonException(f'You cannot unset the {name!r} variable because it is already set')
        self.unset_vars.add(name)

    def append(self, name: str, values: T.List[str], separator: str = os.pathsep) -> None:
        if name in self.unset_vars:
            raise MesonException(f'You cannot append to unset variable {name!r}')
        self.varnames.add(name)
        self.envvars.append((self._append, name, values, separator))

    def prepend(self, name: str, values: T.List[str], separator: str = os.pathsep) -> None:
        if name in self.unset_vars:
            raise MesonException(f'You cannot prepend to unset variable {name!r}')
        self.varnames.add(name)
        self.envvars.append((self._prepend, name, values, separator))

    @staticmethod
    def _set(env: T.Dict[str, str], name: str, values: T.List[str], separator: str, default_value: T.Optional[str]) -> str:
        return separator.join(values)

    @staticmethod
    def _append(env: T.Dict[str, str], name: str, values: T.List[str], separator: str, default_value: T.Optional[str]) -> str:
        curr = env.get(name, default_value)
        return separator.join(values if curr is None else [curr] + values)

    @staticmethod
    def _prepend(env: T.Dict[str, str], name: str, values: T.List[str], separator: str, default_value: T.Optional[str]) -> str:
        curr = env.get(name, default_value)
        return separator.join(values if curr is None else values + [curr])

    def get_env(self, full_env: EnvironOrDict, default_fmt: T.Optional[str] = None) -> T.Dict[str, str]:
        env = full_env.copy()
        for method, name, values, separator in self.envvars:
            default_value = default_fmt.format(name) if default_fmt else None
            env[name] = method(env, name, values, separator, default_value)
        for name in self.unset_vars:
            env.pop(name, None)
        return env


@dataclass(eq=False)
class ExecutableSerialisation:

    cmd_args: T.List[str]
    env: T.Optional[EnvironmentVariables] = None
    exe_wrapper: T.Optional['programs.ExternalProgram'] = None
    workdir: T.Optional[str] = None
    extra_paths: T.Optional[T.List] = None
    capture: T.Optional[str] = None
    feed: T.Optional[str] = None
    tag: T.Optional[str] = None
    verbose: bool = False
    installdir_map: T.Optional[T.Dict[str, str]] = None

    def __post_init__(self) -> None:
        self.pickled = False
        self.skip_if_destdir = False
        self.subproject = ''
        self.dry_run = False
