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

"""
Miscellaneous modeling utilities.
"""

import os
from json import JSONEncoder
from StringIO import StringIO

from . import exceptions
from ..utils.type import validate_value_type
from ..utils.collections import OrderedDict
from ..utils.formatting import string_list_as_string


class ModelJSONEncoder(JSONEncoder):
    """
    JSON encoder that automatically unwraps ``value`` attributes.
    """
    def __init__(self, *args, **kwargs):
        # Just here to make sure Sphinx doesn't grab the base constructor's docstring
        super(ModelJSONEncoder, self).__init__(*args, **kwargs)

    def default(self, o):  # pylint: disable=method-hidden
        try:
            if hasattr(o, 'value'):
                dict_to_return = o.to_dict(fields=('value',))
                return dict_to_return['value']
            else:
                return o.to_dict()
        except AttributeError:
            return JSONEncoder.default(self, o)


class NodeTemplateContainerHolder(object):
    """
    Wrapper that allows using a :class:`~aria.modeling.models.NodeTemplate` model directly as the
    ``container_holder`` input for :func:`~aria.modeling.functions.evaluate`.
    """

    def __init__(self, node_template):
        self.container = node_template
        self.service = None

    @property
    def service_template(self):
        return self.container.service_template


def validate_no_undeclared_inputs(declared_inputs, supplied_inputs):

    undeclared_inputs = [input for input in supplied_inputs if input not in declared_inputs]
    if undeclared_inputs:
        raise exceptions.UndeclaredInputsException(
            'Undeclared inputs have been provided: {0}; Declared inputs: {1}'
            .format(string_list_as_string(undeclared_inputs),
                    string_list_as_string(declared_inputs.keys())))


def validate_required_inputs_are_supplied(declared_inputs, supplied_inputs):
    required_inputs = [input for input in declared_inputs.values() if input.required]
    missing_required_inputs = [input for input in required_inputs
                               if input.name not in supplied_inputs and not input.value]
    if missing_required_inputs:
        raise exceptions.MissingRequiredInputsException(
            'Required inputs {0} have not been provided values'
            .format(string_list_as_string(missing_required_inputs)))


def merge_parameter_values(provided_values, declared_parameters, model_cls=None):
    """
    Merges parameter values according to those declared by a type.

    Exceptions will be raised for validation errors.

    :param provided_values: provided parameter values or None
    :type provided_values: {:obj:`basestring`: object}
    :param declared_parameters: declared parameters
    :type declared_parameters: {:obj:`basestring`: :class:`~aria.modeling.models.Parameter`}
    :param model_cls: the model class that should be created from a provided value
    :type model_cls: :class:`~aria.modeling.models.Input` or :class:`~aria.modeling.models.Argument`
    :return: the merged parameters
    :rtype: {:obj:`basestring`: :class:`~aria.modeling.models.Parameter`}
    :raises ~aria.modeling.exceptions.UndeclaredInputsException: if a key in
     ``parameter_values`` does not exist in ``declared_parameters``
    :raises ~aria.modeling.exceptions.MissingRequiredInputsException: if a key in
     ``declared_parameters`` does not exist in ``parameter_values`` and also has no default value
    :raises ~aria.modeling.exceptions.ParametersOfWrongTypeException: if a value in
      ``parameter_values`` does not match its type in ``declared_parameters``
    """

    provided_values = provided_values or {}
    provided_values_of_wrong_type = OrderedDict()
    model_parameters = OrderedDict()
    model_cls = model_cls or _get_class_from_sql_relationship(declared_parameters)

    for declared_parameter_name, declared_parameter in declared_parameters.iteritems():
        if declared_parameter_name in provided_values:
            # a value has been provided
            value = provided_values[declared_parameter_name]

            # Validate type
            type_name = declared_parameter.type_name
            try:
                validate_value_type(value, type_name)
            except ValueError:
                provided_values_of_wrong_type[declared_parameter_name] = type_name
            except RuntimeError:
                # TODO This error shouldn't be raised (or caught), but right now we lack support
                # for custom data_types, which will raise this error. Skipping their validation.
                pass
            model_parameters[declared_parameter_name] = model_cls(                                  # pylint: disable=unexpected-keyword-arg
                name=declared_parameter_name,
                type_name=type_name,
                description=declared_parameter.description,
                value=value)
        else:
            # Copy default value from declaration
            model_parameters[declared_parameter_name] = model_cls(
                value=declared_parameter._value,
                name=declared_parameter.name,
                type_name=declared_parameter.type_name,
                description=declared_parameter.description)

    if provided_values_of_wrong_type:
        error_message = StringIO()
        for param_name, param_type in provided_values_of_wrong_type.iteritems():
            error_message.write('Parameter "{0}" is not of declared type "{1}"{2}'
                                .format(param_name, param_type, os.linesep))
        raise exceptions.ParametersOfWrongTypeException(error_message.getvalue())

    return model_parameters


def parameters_as_values(the_dict):
    return dict((k, v.value) for k, v in the_dict.iteritems())


def dict_as_arguments(the_dict):
    return OrderedDict((name, value.as_argument()) for name, value in the_dict.iteritems())


class classproperty(object):                                                                        # pylint: disable=invalid-name
    def __init__(self, f):
        self._func = f
        self.__doct__ = f.__doc__

    def __get__(self, instance, owner):
        return self._func(owner)


def fix_doc(cls):
    """
    Class decorator to use the last base class's docstring and make sure Sphinx doesn't grab the
    base constructor's docstring.
    """
    original_init = cls.__init__
    def init(*args, **kwargs):
        original_init(*args, **kwargs)

    cls.__init__ = init
    cls.__doc__ = cls.__bases__[-1].__doc__

    return cls


def _get_class_from_sql_relationship(field):
    class_ = field._sa_adapter.owner_state.class_
    prop_name = field._sa_adapter.attr.key
    return getattr(class_, prop_name).property.mapper.class_
