# Copyright 2020 The Pigweed Authors
#
# 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
#
#     https://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.
"""The envparse module defines an environment variable parser."""

import argparse
from dataclasses import dataclass
import os
from typing import Callable, Dict, Generic, IO, List, Mapping, Optional, TypeVar
from typing import Union


class EnvNamespace(argparse.Namespace):  # pylint: disable=too-few-public-methods
    """Base class for parsed environment variable namespaces."""


T = TypeVar('T')
TypeConversion = Callable[[str], T]


@dataclass
class VariableDescriptor(Generic[T]):
    name: str
    type: TypeConversion[T]
    default: Optional[T]


class EnvironmentValueError(Exception):
    """Exception indicating a bad type conversion on an environment variable.

    Stores a reference to the lower-level exception from the type conversion
    function through the __cause__ attribute for more detailed information on
    the error.
    """
    def __init__(self, variable: str, value: str):
        self.variable: str = variable
        self.value: str = value
        super().__init__(
            f'Bad value for environment variable {variable}: {value}')


class EnvironmentParser:
    """Parser for environment variables.

    Args:
        prefix: If provided, checks that all registered environment variables
          start with the specified string.
        error_on_unrecognized: If True and prefix is provided, will raise an
          exception if the environment contains a variable with the specified
          prefix that is not registered on the EnvironmentParser. If None,
          checks existence of PW_ENVIRONMENT_NO_ERROR_ON_UNRECOGNIZED (but not
          value).

    Example:

        parser = envparse.EnvironmentParser(prefix='PW_')
        parser.add_var('PW_LOG_LEVEL')
        parser.add_var('PW_LOG_FILE', type=envparse.FileType('w'))
        parser.add_var('PW_USE_COLOR', type=envparse.strict_bool, default=False)
        env = parser.parse_env()

        configure_logging(env.PW_LOG_LEVEL, env.PW_LOG_FILE)
    """
    def __init__(self,
                 prefix: Optional[str] = None,
                 error_on_unrecognized: Union[bool, None] = None) -> None:
        self._prefix: Optional[str] = prefix
        if error_on_unrecognized is None:
            varname = 'PW_ENVIRONMENT_NO_ERROR_ON_UNRECOGNIZED'
            error_on_unrecognized = varname not in os.environ
        self._error_on_unrecognized: bool = error_on_unrecognized

        self._variables: Dict[str, VariableDescriptor] = {}
        self._allowed_suffixes: List[str] = []

    def add_var(
        self,
        name: str,
        # pylint: disable=redefined-builtin
        type: TypeConversion[T] = str,  # type: ignore[assignment]
        # pylint: enable=redefined-builtin
        default: Optional[T] = None,
    ) -> None:
        """Registers an environment variable.

        Args:
            name: The environment variable's name.
            type: Type conversion for the variable's value.
            default: Default value for the variable.

        Raises:
            ValueError: If prefix was provided to the constructor and name does
              not start with the prefix.
        """
        if self._prefix is not None and not name.startswith(self._prefix):
            raise ValueError(
                f'Variable {name} does not have prefix {self._prefix}')

        self._variables[name] = VariableDescriptor(name, type, default)

    def add_allowed_suffix(self, suffix: str) -> None:
        """Registers an environment variable name suffix to be allowed."""

        self._allowed_suffixes.append(suffix)

    def parse_env(self,
                  env: Optional[Mapping[str, str]] = None) -> EnvNamespace:
        """Parses known environment variables into a namespace.

        Args:
            env: Dictionary of environment variables. Defaults to os.environ.

        Raises:
            EnvironmentValueError: If the type conversion fails.
        """
        if env is None:
            env = os.environ

        namespace = EnvNamespace()

        for var, desc in self._variables.items():
            if var not in env:
                val = desc.default
            else:
                try:
                    val = desc.type(env[var])  # type: ignore
                except Exception as err:
                    raise EnvironmentValueError(var, env[var]) from err

            setattr(namespace, var, val)

        allowed_suffixes = tuple(self._allowed_suffixes)
        for var in env:
            if (not hasattr(namespace, var)
                    and (self._prefix is None or var.startswith(self._prefix))
                    and var.endswith(allowed_suffixes)):
                setattr(namespace, var, env[var])

        if self._prefix is not None and self._error_on_unrecognized:
            for var in env:
                if (var.startswith(self._prefix) and var not in self._variables
                        and not var.endswith(allowed_suffixes)):
                    raise ValueError(
                        f'Unrecognized environment variable {var}')

        return namespace

    def __repr__(self) -> str:
        return f'{type(self).__name__}(prefix={self._prefix})'


# List of emoji which are considered to represent "True".
_BOOLEAN_TRUE_EMOJI = set([
    '✔️',
    '👍',
    '👍🏻',
    '👍🏼',
    '👍🏽',
    '👍🏾',
    '👍🏿',
    '💯',
])


def strict_bool(value: str) -> bool:
    return (value == '1' or value.lower() == 'true'
            or value in _BOOLEAN_TRUE_EMOJI)


# TODO(mohrr) Switch to Literal when no longer supporting Python 3.7.
# OpenMode = Literal['r', 'rb', 'w', 'wb']
OpenMode = str


class FileType:
    def __init__(self, mode: OpenMode) -> None:
        self._mode: OpenMode = mode

    def __call__(self, value: str) -> IO:
        return open(value, self._mode)
