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

"""
classes:
    * ModelMixin - abstract model implementation.
    * ModelIDMixin - abstract model implementation with IDs.
"""

from sqlalchemy.ext import associationproxy
from sqlalchemy import (
    Column,
    Integer,
    Text,
    PickleType
)

from ..parser.consumption import ConsumptionContext
from ..utils import console, collections, caching, formatting
from ..utils.type import canonical_type_name, full_type_name
from . import utils, functions


class ModelMixin(object):

    @utils.classproperty
    def __modelname__(cls):                                                                         # pylint: disable=no-self-argument
        return getattr(cls, '__mapiname__', cls.__tablename__)

    @classmethod
    def id_column_name(cls):
        raise NotImplementedError

    @classmethod
    def name_column_name(cls):
        raise NotImplementedError

    def to_dict(self, fields=None, suppress_error=False):
        """
        Return a dict representation of the model

        :param suppress_error: If set to True, sets ``None`` to attributes that it's unable to
                               retrieve (e.g., if a relationship wasn't established yet, and so it's
                               impossible to access a property through it)
        """

        res = dict()
        fields = fields or self.fields()
        for field in fields:
            try:
                field_value = getattr(self, field)
            except AttributeError:
                if suppress_error:
                    field_value = None
                else:
                    raise
            if isinstance(field_value, list):
                field_value = list(field_value)
            elif isinstance(field_value, dict):
                field_value = dict(field_value)
            elif isinstance(field_value, ModelMixin):
                field_value = field_value.to_dict()
            res[field] = field_value

        return res

    @classmethod
    def fields(cls):
        """
        Return the list of field names for this table

        Mostly for backwards compatibility in the code (that uses ``fields``)
        """

        fields = set(cls._iter_association_proxies())
        fields.update(cls.__table__.columns.keys())
        return fields - set(getattr(cls, '__private_fields__', []))

    @classmethod
    def _iter_association_proxies(cls):
        for col, value in vars(cls).items():
            if isinstance(value, associationproxy.AssociationProxy):
                yield col

    def __repr__(self):
        return '<{cls} id=`{id}`>'.format(
            cls=self.__class__.__name__,
            id=getattr(self, self.name_column_name()))


class ModelIDMixin(object):
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(Text, index=True)

    @classmethod
    def id_column_name(cls):
        return 'id'

    @classmethod
    def name_column_name(cls):
        return 'name'


class InstanceModelMixin(ModelMixin):
    """
    Mixin for :class:`ServiceInstance` models.

    All models support validation, diagnostic dumping, and representation as
    raw data (which can be translated into JSON or YAML) via ``as_raw``.
    """

    @property
    def as_raw(self):
        raise NotImplementedError

    def validate(self):
        pass

    def coerce_values(self, report_issues):
        pass

    def dump(self):
        pass


class TemplateModelMixin(InstanceModelMixin):
    """
    Mixin for :class:`ServiceTemplate` models.

    All model models can be instantiated into :class:`ServiceInstance` models.
    """

    def instantiate(self, container):
        raise NotImplementedError


class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):                                 #pylint: disable=abstract-method
    """
    Represents a typed value. The value can contain nested intrinsic functions.

    This model can be used as the ``container_holder`` argument for :func:`functions.evaluate`.

    :ivar name: Name
    :vartype name: basestring
    :ivar type_name: Type name
    :vartype type_name: basestring
    :ivar value: Value
    :ivar description: Description
    :vartype description: basestring
    """

    __tablename__ = 'parameter'

    name = Column(Text)
    type_name = Column(Text)
    description = Column(Text)
    _value = Column(PickleType)

    @property
    def value(self):
        value = self._value
        if value is not None:
            evaluation = functions.evaluate(value, self)
            if evaluation is not None:
                value = evaluation.value
        return value

    @value.setter
    def value(self, value):
        self._value = value

    @property
    @caching.cachedmethod
    def owner(self):
        """
        The sole owner of this parameter, which is another model that relates to it.

        *All* parameters should have an owner model. In case this property method fails to find
        it, it will raise a ValueError, which should signify an abnormal, orphaned parameter.
        """

        # Find first non-null relationship
        for the_relationship in self.__mapper__.relationships:
            v = getattr(self, the_relationship.key)
            if v:
                return v

        raise ValueError('orphaned {class_name}: does not have an owner: {name}'.format(
            class_name=type(self).__name__, name=self.name))

    @property
    @caching.cachedmethod
    def container(self): # pylint: disable=too-many-return-statements,too-many-branches
        """
        The logical container for this parameter, which would be another model: service, node,
        group, or policy (or their templates).

        The logical container is equivalent to the ``SELF`` keyword used by intrinsic functions in
        TOSCA.

        *All* parameters should have a container model. In case this property method fails to find
        it, it will raise a ValueError, which should signify an abnormal, orphaned parameter.
        """

        from . import models

        container = self.owner

        # Extract interface from operation
        if isinstance(container, models.Operation):
            container = container.interface
        elif isinstance(container, models.OperationTemplate):
            container = container.interface_template

        # Extract from other models
        if isinstance(container, models.Interface):
            container = container.node or container.group or container.relationship
        elif isinstance(container, models.InterfaceTemplate):
            container = container.node_template or container.group_template \
                        or container.relationship_template
        elif isinstance(container, models.Capability) or isinstance(container, models.Artifact):
            container = container.node
        elif isinstance(container, models.CapabilityTemplate) \
                or isinstance(container, models.ArtifactTemplate):
            container = container.node_template
        elif isinstance(container, models.Task):
            container = container.actor

        # Extract node from relationship
        if isinstance(container, models.Relationship):
            container = container.source_node
        elif isinstance(container, models.RelationshipTemplate):
            container = container.requirement_template.node_template

        if container is not None:
            return container

        raise ValueError('orphaned parameter: does not have a container: {0}'.format(self.name))

    @property
    @caching.cachedmethod
    def service(self):
        """
        The :class:`Service` containing this parameter, or None if not contained in a service.
        """

        from . import models
        container = self.container
        if isinstance(container, models.Service):
            return container
        elif hasattr(container, 'service'):
            return container.service
        return None

    @property
    @caching.cachedmethod
    def service_template(self):
        """
        The :class:`ServiceTemplate` containing this parameter, or None if not contained in a
        service template.
        """

        from . import models
        container = self.container
        if isinstance(container, models.ServiceTemplate):
            return container
        elif hasattr(container, 'service_template'):
            return container.service_template
        return None

    @property
    def as_raw(self):
        return collections.OrderedDict((
            ('name', self.name),
            ('type_name', self.type_name),
            ('value', self.value),
            ('description', self.description)))

    def instantiate(self, container):
        return self.__class__(name=self.name,  # pylint: disable=unexpected-keyword-arg
                              type_name=self.type_name,
                              _value=self._value,
                              description=self.description)

    def coerce_values(self, report_issues):
        value = self._value
        if value is not None:
            evaluation = functions.evaluate(value, self, report_issues)
            if (evaluation is not None) and evaluation.final:
                # A final evaluation can safely replace the existing value
                self._value = evaluation.value

    def dump(self):
        context = ConsumptionContext.get_thread_local()
        if self.type_name is not None:
            console.puts('{0}: {1} ({2})'.format(
                context.style.property(self.name),
                context.style.literal(formatting.as_raw(self.value)),
                context.style.type(self.type_name)))
        else:
            console.puts('{0}: {1}'.format(
                context.style.property(self.name),
                context.style.literal(formatting.as_raw(self.value))))
        if self.description:
            console.puts(context.style.meta(self.description))

    @property
    def unwrapped(self):
        return self.name, self.value

    @classmethod
    def wrap(cls, name, value, description=None):
        """
        Wraps an arbitrary value as a parameter. The type will be guessed via introspection.

        For primitive types, we will prefer their TOSCA aliases. See the `TOSCA Simple Profile v1.0
        cos01 specification <http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01
        /TOSCA-Simple-Profile-YAML-v1.0-cos01.html#_Toc373867862>`__

        :param name: Parameter name
        :type name: basestring
        :param value: Parameter value
        :param description: Description (optional)
        :type description: basestring
        """

        type_name = canonical_type_name(value)
        if type_name is None:
            type_name = full_type_name(value)
        return cls(name=name,  # pylint: disable=unexpected-keyword-arg
                   type_name=type_name,
                   value=value,
                   description=description)

    def as_other_parameter_model(self, other_model_cls):

        name, value = self.unwrapped
        return other_model_cls.wrap(name, value)

    def as_argument(self):
        from . import models
        return self.as_other_parameter_model(models.Argument)
