# 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.

from aria.utils.collections import deepcopy_with_locators, OrderedDict
from aria.parser.validation import Issue

from .parameters import (convert_parameter_definitions_to_values, merge_raw_parameter_definitions,
                         get_assigned_and_defined_parameter_values)


#
# CapabilityType
#

def get_inherited_valid_source_types(context, presentation):
    """
    If we haven't set the :code:`valid_source_types` fields, uses that value from our parent, if
    we have one (recursively).
    """

    valid_source_types = presentation.valid_source_types

    if valid_source_types is None:
        parent = presentation._get_parent(context)
        valid_source_types = get_inherited_valid_source_types(context, parent) \
            if parent is not None else None

    return valid_source_types


#
# NodeType
#

def get_inherited_capability_definitions(context, presentation, for_presentation=None):
    """
    Returns our capability capability definitions added on top of those of our parent, if we have
    one (recursively).

    Allows overriding all aspects of parent capability properties except data type.
    """

    # Get capability definitions from parent
    parent = presentation._get_parent(context)
    capability_definitions = get_inherited_capability_definitions(context, parent,
                                                                  for_presentation=presentation) \
                                                                  if parent is not None \
                                                                  else OrderedDict()

    # Add/merge our capability definitions
    our_capability_definitions = presentation.capabilities
    if our_capability_definitions:
        for capability_name, our_capability_definition in our_capability_definitions.iteritems():
            if capability_name in capability_definitions:
                capability_definition = capability_definitions[capability_name]

                # Check if we changed the type
                type1 = capability_definition.type
                type2 = our_capability_definition.type
                if type1 != type2:
                    context.validation.report(
                        'capability definition changes type from "%s" to "%s" in "%s"'
                        % (type1, type2, presentation._fullname),
                        locator=our_capability_definition._locator, level=Issue.BETWEEN_TYPES)

                # Already cloned?
                #capability_definition = capability_definition._clone(for_presentation)
                #capability_definitions[capability_name] = capability_definition
            else:
                capability_definition = our_capability_definition._clone(for_presentation)
                if isinstance(capability_definition._raw, basestring):
                    # Make sure we have a dict
                    the_type = capability_definition._raw
                    capability_definition._raw = OrderedDict()
                    capability_definition._raw['type'] = the_type
                capability_definitions[capability_name] = capability_definition

            merge_capability_definition_from_type(context, presentation, capability_definition)

    for capability_definition in capability_definitions.itervalues():
        capability_definition._reset_method_cache()

    return capability_definitions


#
# NodeTemplate
#

def get_template_capabilities(context, presentation):
    """
    Returns the node type's capabilities with our assignments to properties and attributes merged
    in.

    Capability properties' default values, if available, will be used if we did not assign them.

    Makes sure that required properties indeed end up with a value.
    """

    capability_assignments = OrderedDict()

    the_type = presentation._get_type(context) # NodeType
    capability_definitions = the_type._get_capabilities(context) if the_type is not None else None

    # Copy over capability definitions from the type (will initialize properties with default
    # values)
    if capability_definitions:
        for capability_name, capability_definition in capability_definitions.iteritems():
            capability_assignments[capability_name] = \
                convert_capability_from_definition_to_assignment(context, capability_definition,
                                                                 presentation)

    # Fill in our capability assignments
    our_capability_assignments = presentation.capabilities
    if our_capability_assignments:
        for capability_name, our_capability_assignment in our_capability_assignments.iteritems():
            if capability_name in capability_assignments:
                capability_assignment = capability_assignments[capability_name]

                # Assign properties
                values = get_assigned_and_defined_parameter_values(context,
                                                                   our_capability_assignment,
                                                                   'property')
                if values:
                    capability_assignment._raw['properties'] = values
            else:
                context.validation.report(
                    'capability "%s" not declared at node type "%s" in "%s"'
                    % (capability_name, presentation.type, presentation._fullname),
                    locator=our_capability_assignment._locator, level=Issue.BETWEEN_TYPES)

    return capability_assignments


#
# Utils
#

def convert_capability_from_definition_to_assignment(context, presentation, container):
    from ..assignments import CapabilityAssignment

    raw = OrderedDict()

    properties = presentation.properties
    if properties is not None:
        raw['properties'] = convert_parameter_definitions_to_values(context, properties)

    # TODO attributes

    return CapabilityAssignment(name=presentation._name, raw=raw, container=container)


def merge_capability_definition_from_type(context, presentation, capability_definition):
    raw_properties = OrderedDict()

    # Merge properties from type
    the_type = capability_definition._get_type(context)
    type_property_defintions = the_type._get_properties(context)
    merge_raw_parameter_definitions(context, presentation, raw_properties, type_property_defintions,
                                    'properties')

    # Merge our properties
    merge_raw_parameter_definitions(context, presentation, raw_properties,
                                    capability_definition.properties, 'properties')

    if raw_properties:
        capability_definition._raw['properties'] = raw_properties

    # Override valid_source_types
    if capability_definition._raw.get('valid_source_types') is None:
        valid_source_types = the_type._get_valid_source_types(context)
        if valid_source_types is not None:
            capability_definition._raw['valid_source_types'] = \
                deepcopy_with_locators(valid_source_types)
