# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

import re

from aria.modeling.constraints import NodeTemplateConstraint
from aria.modeling.utils import NodeTemplateContainerHolder
from aria.modeling.functions import evaluate
from aria.parser import implements_specification


@implements_specification('3.5.2-2', 'tosca-simple-1.0')
class EvaluatingNodeTemplateConstraint(NodeTemplateConstraint):
    """
    A version of :class:`NodeTemplateConstraint` with boilerplate initialization for TOSCA
    constraints.
    """

    def __init__(self, property_name, capability_name, constraint, as_list=False):
        self.property_name = property_name
        self.capability_name = capability_name
        self.constraint = constraint
        self.as_list = as_list

    def matches(self, source_node_template, target_node_template):
        # TOSCA node template constraints can refer to either capability properties or node
        # template properties
        if self.capability_name is not None:
            # Capability property
            capability = target_node_template.capability_templates.get(self.capability_name)
            value = capability.properties.get(self.property_name) \
                if capability is not None else None # Parameter
        else:
            # Node template property
            value = target_node_template.properties.get(self.property_name) # Parameter

        value = value.value if value is not None else None

        container_holder = NodeTemplateContainerHolder(source_node_template)

        if self.as_list:
            constraints = []
            for constraint in self.constraint:
                evaluation = evaluate(constraint, container_holder)
                if evaluation is not None:
                    constraints.append(evaluation.value)
                else:
                    constraints.append(constraint)
            constraint = constraints
        else:
            evaluation = evaluate(self.constraint, container_holder)
            if evaluation is not None:
                constraint = evaluation.value
            else:
                constraint = self.constraint

        return self.matches_evaluated(value, constraint)

    def matches_evaluated(self, value, constraint):
        raise NotImplementedError


class Equal(EvaluatingNodeTemplateConstraint):
    def matches_evaluated(self, value, constraint):
        return value == constraint


class GreaterThan(EvaluatingNodeTemplateConstraint):
    def matches_evaluated(self, value, constraint):
        return value > constraint


class GreaterOrEqual(EvaluatingNodeTemplateConstraint):
    def matches_evaluated(self, value, constraint):
        return value >= constraint


class LessThan(EvaluatingNodeTemplateConstraint):
    def matches_evaluated(self, value, constraint):
        return value < constraint


class LessOrEqual(EvaluatingNodeTemplateConstraint):
    def matches_evaluated(self, value, constraint):
        return value <= constraint


class InRange(EvaluatingNodeTemplateConstraint):
    def __init__(self, property_name, capability_name, constraint):
        super(InRange, self).__init__(property_name, capability_name, constraint, as_list=True)

    def matches_evaluated(self, value, constraints):
        lower, upper = constraints
        if value < lower:
            return False
        if (upper != 'UNBOUNDED') and (value > upper):
            return False
        return True


class ValidValues(EvaluatingNodeTemplateConstraint):
    def __init__(self, property_name, capability_name, constraint):
        super(ValidValues, self).__init__(property_name, capability_name, constraint, as_list=True)

    def matches_evaluated(self, value, constraints):
        return value in constraints


class Length(EvaluatingNodeTemplateConstraint):
    def matches_evaluated(self, value, constraint):
        return len(value) == constraint


class MinLength(EvaluatingNodeTemplateConstraint):
    def matches_evaluated(self, value, constraint):
        return len(value) >= constraint


class MaxLength(EvaluatingNodeTemplateConstraint):
    def matches_evaluated(self, value, constraint):
        return len(value) <= constraint


class Pattern(EvaluatingNodeTemplateConstraint):
    def matches_evaluated(self, value, constraint):
        # From TOSCA 1.0 3.5.2.1:
        #
        # "Note: Future drafts of this specification will detail the use of regular expressions and
        # reference an appropriate standardized grammar."
        #
        # So we will just use Python's.
        return re.match(constraint, unicode(value)) is not None
