#
#    Copyright (c) 2022 Project CHIP Authors
#    All rights reserved.
#
#    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 abc import ABC, abstractmethod
import chip.yaml.format_converter as Converter
from .variable_storage import VariableStorage


class ConstraintValidationError(Exception):
    def __init__(self, message):
        super().__init__(message)


class BaseConstraint(ABC):
    '''Constrain Interface'''

    @abstractmethod
    def is_met(self, response) -> bool:
        pass


class _LoadableConstraint(BaseConstraint):
    '''Constraints where value might be stored in VariableStorage needing runtime load.'''

    def __init__(self, value, field_type, variable_storage: VariableStorage):
        self._variable_storage = variable_storage
        # When not none _indirect_value_key is binding a name to the constraint value, and the
        # actual value can only be looked-up dynamically, which is why this is a key name.
        self._indirect_value_key = None
        self._value = None

        if value is None:
            # Default values set above is all we need here.
            return

        if isinstance(value, str) and self._variable_storage.is_key_saved(value):
            self._indirect_value_key = value
        else:
            self._value = Converter.convert_yaml_type(
                value, field_type)

    def get_value(self):
        '''Gets the current value of the constraint.

        This method accounts for getting the runtime saved value from DUT previous responses.
        '''
        if self._indirect_value_key:
            return self._variable_storage.load(self._indirect_value_key)
        return self._value


class _ConstraintHasValue(BaseConstraint):
    def __init__(self, has_value):
        self._has_value = has_value

    def is_met(self, response) -> bool:
        raise ConstraintValidationError('HasValue constraint currently not implemented')


class _ConstraintType(BaseConstraint):
    def __init__(self, type):
        self._type = type

    def is_met(self, response) -> bool:
        raise ConstraintValidationError('Type constraint currently not implemented')


class _ConstraintStartsWith(BaseConstraint):
    def __init__(self, starts_with):
        self._starts_with = starts_with

    def is_met(self, response) -> bool:
        return response.startswith(self._starts_with)


class _ConstraintEndsWith(BaseConstraint):
    def __init__(self, ends_with):
        self._ends_with = ends_with

    def is_met(self, response) -> bool:
        return response.endswith(self._ends_with)


class _ConstraintIsUpperCase(BaseConstraint):
    def __init__(self, is_upper_case):
        self._is_upper_case = is_upper_case

    def is_met(self, response) -> bool:
        return response.isupper() == self._is_upper_case


class _ConstraintIsLowerCase(BaseConstraint):
    def __init__(self, is_lower_case):
        self._is_lower_case = is_lower_case

    def is_met(self, response) -> bool:
        return response.islower() == self._is_lower_case


class _ConstraintMinValue(_LoadableConstraint):
    def __init__(self, min_value, field_type, variable_storage: VariableStorage):
        super().__init__(min_value, field_type, variable_storage)

    def is_met(self, response) -> bool:
        min_value = self.get_value()
        return response >= min_value


class _ConstraintMaxValue(_LoadableConstraint):
    def __init__(self, max_value, field_type, variable_storage: VariableStorage):
        super().__init__(max_value, field_type, variable_storage)

    def is_met(self, response) -> bool:
        max_value = self.get_value()
        return response <= max_value


class _ConstraintContains(BaseConstraint):
    def __init__(self, contains):
        self._contains = contains

    def is_met(self, response) -> bool:
        return set(self._contains).issubset(response)


class _ConstraintExcludes(BaseConstraint):
    def __init__(self, excludes):
        self._excludes = excludes

    def is_met(self, response) -> bool:
        return set(self._excludes).isdisjoint(response)


class _ConstraintHasMaskSet(BaseConstraint):
    def __init__(self, has_masks_set):
        self._has_masks_set = has_masks_set

    def is_met(self, response) -> bool:
        return all([(response & mask) == mask for mask in self._has_masks_set])


class _ConstraintHasMaskClear(BaseConstraint):
    def __init__(self, has_masks_clear):
        self._has_masks_clear = has_masks_clear

    def is_met(self, response) -> bool:
        return all([(response & mask) == 0 for mask in self._has_masks_clear])


class _ConstraintNotValue(_LoadableConstraint):
    def __init__(self, not_value, field_type, variable_storage: VariableStorage):
        super().__init__(not_value, field_type, variable_storage)

    def is_met(self, response) -> bool:
        not_value = self.get_value()
        return response != not_value


def get_constraints(constraints, field_type,
                    variable_storage: VariableStorage) -> list[BaseConstraint]:
    _constraints = []
    if 'hasValue' in constraints:
        _constraints.append(_ConstraintHasValue(constraints.get('hasValue')))

    if 'type' in constraints:
        _constraints.append(_ConstraintType(constraints.get('type')))

    if 'startsWith' in constraints:
        _constraints.append(_ConstraintStartsWith(constraints.get('startsWith')))

    if 'endsWith' in constraints:
        _constraints.append(_ConstraintEndsWith(constraints.get('endsWith')))

    if 'isUpperCase' in constraints:
        _constraints.append(_ConstraintIsUpperCase(constraints.get('isUpperCase')))

    if 'isLowerCase' in constraints:
        _constraints.append(_ConstraintIsLowerCase(constraints.get('isLowerCase')))

    if 'minValue' in constraints:
        _constraints.append(_ConstraintMinValue(
            constraints.get('minValue'), field_type, variable_storage))

    if 'maxValue' in constraints:
        _constraints.append(_ConstraintMaxValue(
            constraints.get('maxValue'), field_type, variable_storage))

    if 'contains' in constraints:
        _constraints.append(_ConstraintContains(constraints.get('contains')))

    if 'excludes' in constraints:
        _constraints.append(_ConstraintExcludes(constraints.get('excludes')))

    if 'hasMasksSet' in constraints:
        _constraints.append(_ConstraintHasMaskSet(constraints.get('hasMasksSet')))

    if 'hasMasksClear' in constraints:
        _constraints.append(_ConstraintHasMaskClear(constraints.get('hasMasksClear')))

    if 'notValue' in constraints:
        _constraints.append(_ConstraintNotValue(
            constraints.get('notValue'), field_type, variable_storage))

    return _constraints
