# 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 threading
from functools import wraps
from types import MethodType

from ...exceptions import AriaException
from ...utils.collections import FrozenDict, FrozenList, deepcopy_with_locators, merge, OrderedDict
from ...utils.caching import cachedmethod
from ...utils.console import puts
from ...utils.formatting import as_raw, safe_repr
from ...utils.type import full_type_name
from ...utils.exceptions import print_exception
from ..exceptions import InvalidValueError

from .null import NULL
from .utils import validate_primitive

#
# Class decorators
#

# pylint: disable=unused-argument

def has_fields(cls):
    """
    Class decorator for validated field support.

    1. Adds a ``FIELDS`` class property that is a dict of all the fields. Will inherit and merge
       ``FIELDS`` properties from base classes if they have them.

    2. Generates automatic ``@property`` implementations for the fields with the help of a set of
       special function decorators.

    The class also works with the Python dict protocol, so that fields can be accessed via dict
    semantics. The functionality is identical to that of using attribute access.

    The class will also gain two utility methods, ``_iter_field_names`` and ``_iter_fields``.
    """

    # Make sure we have FIELDS
    if 'FIELDS' not in cls.__dict__:
        setattr(cls, 'FIELDS', OrderedDict())

    # Inherit FIELDS from base classes
    for base in cls.__bases__:
        if hasattr(base, 'FIELDS'):
            cls.FIELDS.update(base.FIELDS)

    # We could do this:
    #
    #  for name, field in cls.__dict__.iteritems():
    #
    # But dir() is better because it has a deterministic order (alphabetical)

    for name in dir(cls):
        field = getattr(cls, name)

        if isinstance(field, Field):
            # Accumulate
            cls.FIELDS[name] = field

            field.name = name
            field.container_cls = cls

            # This function is here just to create an enclosed scope for "field"
            def closure(field):

                # By convention, we have the getter wrap the original function.
                # (It is, for example, where the Python help() function will look for
                # docstrings when encountering a property.)
                @cachedmethod
                @wraps(field.func)
                def getter(self):
                    return field.get(self, None)

                def setter(self, value):
                    field.set(self, None, value)

                # Convert to Python property
                return property(fget=getter, fset=setter)

            setattr(cls, name, closure(field))

    # Bind methods
    setattr(cls, '_iter_field_names', MethodType(has_fields_iter_field_names, None, cls))
    setattr(cls, '_iter_fields', MethodType(has_fields_iter_fields, None, cls))

    # Behave like a dict
    setattr(cls, '__len__', MethodType(has_fields_len, None, cls))
    setattr(cls, '__getitem__', MethodType(has_fields_getitem, None, cls))
    setattr(cls, '__setitem__', MethodType(has_fields_setitem, None, cls))
    setattr(cls, '__delitem__', MethodType(has_fields_delitem, None, cls))
    setattr(cls, '__iter__', MethodType(has_fields_iter, None, cls))
    setattr(cls, '__contains__', MethodType(has_fields_contains, None, cls))

    return cls


def short_form_field(name):
    """
    Class decorator for specifying the short form field.

    The class must be decorated with :func:`has_fields`.
    """

    def decorator(cls):
        if hasattr(cls, name) and hasattr(cls, 'FIELDS') and (name in cls.FIELDS):
            setattr(cls, 'SHORT_FORM_FIELD', name)
            return cls
        else:
            raise AttributeError('@short_form_field must be used with '
                                 'a Field name in @has_fields class')
    return decorator


def allow_unknown_fields(cls):
    """
    Class decorator specifying that the class allows unknown fields.

    The class must be decorated with :func:`has_fields`.
    """

    if hasattr(cls, 'FIELDS'):
        setattr(cls, 'ALLOW_UNKNOWN_FIELDS', True)
        return cls
    else:
        raise AttributeError('@allow_unknown_fields must be used with a @has_fields class')

#
# Method decorators
#


def primitive_field(cls=None, default=None, allowed=None, required=False):
    """
    Method decorator for primitive fields.

    The function must be a method in a class decorated with :func:`has_fields`.
    """

    def decorator(func):
        return Field(field_variant='primitive', func=func, cls=cls, default=default,
                     allowed=allowed, required=required)
    return decorator


def primitive_list_field(cls=None, default=None, allowed=None, required=False):
    """
    Method decorator for list of primitive fields.

    The function must be a method in a class decorated with :func:`has_fields`.
    """

    def decorator(func):
        return Field(field_variant='primitive_list', func=func, cls=cls, default=default,
                     allowed=allowed, required=required)
    return decorator


def primitive_dict_field(cls=None, default=None, allowed=None, required=False):
    """
    Method decorator for dict of primitive fields.

    The function must be a method in a class decorated with :func:`has_fields`.
    """
    def decorator(func):
        return Field(field_variant='primitive_dict', func=func, cls=cls, default=default,
                     allowed=allowed, required=required)
    return decorator


def primitive_dict_unknown_fields(cls=None, default=None, allowed=None, required=False):
    """
    Method decorator for dict of primitive fields, for all the fields that are
    not already decorated.

    The function must be a method in a class decorated with :func:`has_fields`.
    """

    def decorator(func):
        return Field(field_variant='primitive_dict_unknown_fields', func=func, cls=cls,
                     default=default, allowed=allowed, required=required)
    return decorator


def object_field(cls, default=None, allowed=None, required=False):
    """
    Method decorator for object fields.

    The function must be a method in a class decorated with :func:`has_fields`.
    """
    def decorator(func):
        return Field(field_variant='object', func=func, cls=cls, default=default, allowed=allowed,
                     required=required)
    return decorator


def object_list_field(cls, default=None, allowed=None, required=False):
    """
    Method decorator for list of object fields.

    The function must be a method in a class decorated with :func:`has_fields`.
    """

    def decorator(func):
        return Field(field_variant='object_list', func=func, cls=cls, default=default,
                     allowed=allowed, required=required)
    return decorator


def object_dict_field(cls, default=None, allowed=None, required=False):
    """
    Method decorator for dict of object fields.

    The function must be a method in a class decorated with :func:`has_fields`.
    """

    def decorator(func):
        return Field(field_variant='object_dict', func=func, cls=cls, default=default,
                     allowed=allowed, required=required)
    return decorator


def object_sequenced_list_field(cls, default=None, allowed=None, required=False):
    """
    Method decorator for sequenced list of object fields.

    The function must be a method in a class decorated with :func:`has_fields`.
    """

    def decorator(func):
        return Field(field_variant='sequenced_object_list', func=func, cls=cls, default=default,
                     allowed=allowed, required=required)
    return decorator


def object_dict_unknown_fields(cls, default=None, allowed=None, required=False):
    """
    Method decorator for dict of object fields, for all the fields that are not already decorated.

    The function must be a method in a class decorated with :func:`has_fields`.
    """
    def decorator(func):
        return Field(field_variant='object_dict_unknown_fields', func=func, cls=cls,
                     default=default, allowed=allowed, required=required)
    return decorator


def field_getter(getter_func):
    """
    Method decorator for overriding the getter function of a field.

    The signature of the getter function must be: ``f(field, presentation, context)``.
    The default getter can be accessed as ```field.default_get(presentation, context)``.

    The function must already be decorated with a field decorator.
    """

    def decorator(field):
        if isinstance(field, Field):
            field.get = MethodType(getter_func, field, Field)
            return field
        else:
            raise AttributeError('@field_getter must be used with a Field')
    return decorator


def field_setter(setter_func):
    """
    Method decorator for overriding the setter function of a field.

    The signature of the setter function must be: ``f(field, presentation, context, value)``.
    The default setter can be accessed as ``field.default_set(presentation, context, value)``.

    The function must already be decorated with a field decorator.
    """

    def decorator(field):
        if isinstance(field, Field):
            field.set = MethodType(setter_func, field, Field)
            return field
        else:
            raise AttributeError('@field_setter must be used with a Field')
    return decorator


def field_validator(validator_fn):
    """
    Method decorator for overriding the validator function of a field.

    The signature of the validator function must be: ``f(field, presentation, context)``.
    The default validator can be accessed as ``field.default_validate(presentation, context)``.

    The function must already be decorated with a field decorator.
    """

    def decorator(field):
        if isinstance(field, Field):
            field.validate = MethodType(validator_fn, field, Field)
            return field
        else:
            raise AttributeError('@field_validator must be used with a Field')
    return decorator

#
# Utils
#


def has_fields_iter_field_names(self):
    for name in self.__class__.FIELDS:
        yield name


def has_fields_iter_fields(self):
    return self.FIELDS.iteritems()


def has_fields_len(self):
    return len(self.__class__.FIELDS)


def has_fields_getitem(self, key):
    if not isinstance(key, basestring):
        raise TypeError('key must be a string')
    if key not in self.__class__.FIELDS:
        raise KeyError('no \'{0}\' property'.format(key))
    return getattr(self, key)


def has_fields_setitem(self, key, value):
    if not isinstance(key, basestring):
        raise TypeError('key must be a string')
    if key not in self.__class__.FIELDS:
        raise KeyError('no \'{0}\' property'.format(key))
    return setattr(self, key, value)


def has_fields_delitem(self, key):
    if not isinstance(key, basestring):
        raise TypeError('key must be a string')
    if key not in self.__class__.FIELDS:
        raise KeyError('no \'{0}\' property'.format(key))
    return setattr(self, key, None)


def has_fields_iter(self):
    return self.__class__.FIELDS.iterkeys()


def has_fields_contains(self, key):
    if not isinstance(key, basestring):
        raise TypeError('key must be a string')
    return key in self.__class__.FIELDS


class Field(object):
    """
    Field handler used by ``@has_fields`` decorator.
    """

    def __init__(self, field_variant, func, cls=None, default=None, allowed=None, required=False):
        if cls == str:
            # Use "unicode" instead of "str"
            cls = unicode

        self.container_cls = None
        self.name = None
        self.field_variant = field_variant
        self.func = func
        self.cls = cls
        self.default = default
        self.allowed = allowed
        self.required = required

    @property
    def full_name(self):
        return u'field "{0}" in "{1}"'.format(self.name, full_type_name(self.container_cls))

    @property
    def full_cls_name(self):
        name = full_type_name(self.cls)
        if name == 'unicode':
            # For simplicity, display "unicode" as "str"
            name = 'str'
        return name

    def get(self, presentation, context):
        return self.default_get(presentation, context)

    def set(self, presentation, context, value):
        return self.default_set(presentation, context, value)

    def validate(self, presentation, context):
        self.default_validate(presentation, context)

    def get_locator(self, raw):
        if hasattr(raw, '_locator'):
            locator = raw._locator
            if locator is not None:
                return locator.get_child(self.name)
        return None

    def dump(self, presentation, context):
        value = getattr(presentation, self.name)
        if value is None:
            return

        dumper = getattr(self, '_dump_{0}'.format(self.field_variant))
        dumper(context, value)

    def default_get(self, presentation, context):
        # Handle raw

        default_raw = (presentation._get_default_raw()
                       if hasattr(presentation, '_get_default_raw')
                       else None)

        if default_raw is None:
            raw = presentation._raw
        else:
            # Handle default raw value
            raw = deepcopy_with_locators(default_raw)
            merge(raw, presentation._raw)

        # Handle unknown fields (only dict can have unknown fields, lists can't have them)

        if self.field_variant == 'primitive_dict_unknown_fields':
            return self._get_primitive_dict_unknown_fields(presentation, raw, context)
        elif self.field_variant == 'object_dict_unknown_fields':
            return self._get_object_dict_unknown_fields(presentation, raw, context)

        is_short_form_field = (self.container_cls.SHORT_FORM_FIELD == self.name
                               if hasattr(self.container_cls, 'SHORT_FORM_FIELD')
                               else False)
        is_dict = isinstance(raw, dict)

        # Find value

        value = self._find_value(is_short_form_field, is_dict, raw)

        # Handle required

        if value is None:
            if self.required:
                raise InvalidValueError(u'required {0} does not have a value'
                                        .format(self.full_name, locator=self.get_locator(raw)))
            else:
                return None

        # Handle allowed values

        if self.allowed is not None:
            if value not in self.allowed:
                raise InvalidValueError(u'{0} is not {1}'
                                        .format(self.full_name,
                                                u' or '.join([safe_repr(v) for v in self.allowed])),
                                        locator=self.get_locator(raw))

        # Handle get according to variant

        getter = getattr(self, '_get_{0}'.format(self.field_variant), None)

        if getter is None:
            locator = self.get_locator(raw)
            location = (u' @{0}'.format(locator)) if locator is not None else ''
            raise AttributeError(u'{0} has unsupported field variant: "{1}"{2}'
                                 .format(self.full_name, self.field_variant, location))

        return getter(presentation, raw, value, context)

    def _find_value(self, is_short_form_field, is_dict, raw):
        value = None
        if is_short_form_field and not is_dict:
            # Handle short form
            value = raw
            if value is None:
                # An explicit null
                value = NULL
        elif is_dict:
            if self.name in raw:
                value = raw[self.name]
                if value is None:
                    # An explicit null
                    value = NULL
            else:
                value = self.default
        return value

    def default_set(self, presentation, context, value):
        raw = presentation._raw
        old = self.get(presentation, context)
        raw[self.name] = value
        try:
            self.validate(presentation, context)
        except Exception as e:
            raw[self.name] = old
            raise e
        return old

    def default_validate(self, presentation, context):
        value = None

        try:
            value = self.get(presentation, context)
        except AriaException as e:
            if e.issue:
                context.validation.report(issue=e.issue)
        except Exception as e:
            context.validation.report(exception=e)
            print_exception(e)

        self.validate_value(value, context)

    def validate_value(self, value, context):
        if isinstance(value, list):
            if self.field_variant == 'object_list':
                for element in value:
                    if hasattr(element, '_validate'):
                        element._validate(context)
            elif self.field_variant == 'sequenced_object_list':
                for _, element in value:
                    if hasattr(element, '_validate'):
                        element._validate(context)
        elif isinstance(value, dict):
            if self.field_variant in ('object_dict', 'object_dict_unknown_fields'):
                for inner_value in value.itervalues():
                    if hasattr(inner_value, '_validate'):
                        inner_value._validate(context)

        if hasattr(value, '_validate'):
            value._validate(context)

    @staticmethod
    def _get_context():
        thread_locals = threading.local()
        return getattr(thread_locals, 'aria_consumption_context', None)

    def _coerce_primitive(self, value, context):
        if context is None:
            context = Field._get_context()
        allow_primitive_coercion = (context.validation.allow_primitive_coersion
                                    if context is not None
                                    else True)
        return validate_primitive(value, self.cls, allow_primitive_coercion)

    # primitive

    def _get_primitive(self, presentation, raw, value, context):
        if (self.cls is not None) and (not isinstance(value, self.cls)) \
                and (value is not None):
            try:
                return self._coerce_primitive(value, context)
            except ValueError as e:
                raise InvalidValueError(u'{0} is not a valid "{1}": {2}'
                                        .format(self.full_name, self.full_cls_name,
                                                safe_repr(value)),
                                        locator=self.get_locator(raw), cause=e)
        return value

    def _dump_primitive(self, context, value):
        if hasattr(value, 'as_raw'):
            value = as_raw(value)
        puts(u'{0}: {1}'.format(self.name, context.style.literal_style(value)))

    # primitive list

    def _get_primitive_list(self, presentation, raw, value, context):
        if not isinstance(value, list):
            raise InvalidValueError(u'{0} is not a list: {1}'
                                    .format(self.full_name, safe_repr(value)),
                                    locator=self.get_locator(raw))
        primitive_list = value
        if self.cls is not None:
            if context is None:
                context = Field._get_context()
            primitive_list = []
            for i, _ in enumerate(value):
                primitive = value[i]
                if primitive is None:
                    primitive = NULL
                try:
                    primitive = self._coerce_primitive(primitive, context)
                except ValueError as e:
                    raise InvalidValueError(u'{0} is not a list of "{1}": element {2:d} is {3}'
                                            .format(self.full_name,
                                                    self.full_cls_name,
                                                    i,
                                                    safe_repr(primitive)),
                                            locator=self.get_locator(raw), cause=e)
                if primitive in primitive_list:
                    raise InvalidValueError(u'{0} has a duplicate "{1}": {2}'
                                            .format(self.full_name,
                                                    self.full_cls_name,
                                                    safe_repr(primitive)),
                                            locator=self.get_locator(raw))
                primitive_list.append(primitive)
        return FrozenList(primitive_list)

    def _dump_primitive_list(self, context, value):
        puts(u'{0}:'.format(self.name))
        with context.style.indent():
            for primitive in value:
                if hasattr(primitive, 'as_raw'):
                    primitive = as_raw(primitive)
                puts(context.style.literal_style(primitive))

    # primitive dict

    def _get_primitive_dict(self, presentation, raw, value, context):
        if not isinstance(value, dict):
            raise InvalidValueError(u'{0} is not a dict: {1}'
                                    .format(self.full_name, safe_repr(value)),
                                    locator=self.get_locator(raw))
        primitive_dict = value
        if self.cls is not None:
            if context is None:
                context = Field._get_context()
            primitive_dict = OrderedDict()
            for k, v in value.iteritems():
                if v is None:
                    v = NULL
                try:
                    primitive_dict[k] = self._coerce_primitive(v, context)
                except ValueError as e:
                    raise InvalidValueError(u'{0} is not a dict of "{1}" values: entry "{2:d}" '
                                            u'is {3}'
                                            .format(self.full_name, self.full_cls_name, k,
                                                    safe_repr(v)),
                                            locator=self.get_locator(raw),
                                            cause=e)
        return FrozenDict(primitive_dict)

    def _dump_primitive_dict(self, context, value):
        puts(u'{0}:'.format(self.name))
        with context.style.indent():
            for v in value.itervalues():
                if hasattr(v, 'as_raw'):
                    v = as_raw(v)
                puts(context.style.literal_style(v))

    # object

    def _get_object(self, presentation, raw, value, context):
        try:
            return self.cls(name=self.name, raw=value, container=presentation)
        except TypeError as e:
            raise InvalidValueError(u'{0} cannot not be initialized to an instance of "{1}": {2}'
                                    .format(self.full_name, self.full_cls_name, safe_repr(value)),
                                    cause=e,
                                    locator=self.get_locator(raw))

    def _dump_object(self, context, value):
        puts(u'{0}:'.format(self.name))
        with context.style.indent():
            if hasattr(value, '_dump'):
                value._dump(context)

    # object list

    def _get_object_list(self, presentation, raw, value, context):
        if not isinstance(value, list):
            raise InvalidValueError(u'{0} is not a list: {1}'
                                    .format(self.full_name, safe_repr(value)),
                                    locator=self.get_locator(raw))
        return FrozenList((self.cls(name=self.name, raw=v, container=presentation) for v in value))

    def _dump_object_list(self, context, value):
        puts(u'{0}:'.format(self.name))
        with context.style.indent():
            for v in value:
                if hasattr(v, '_dump'):
                    v._dump(context)

    # object dict

    def _get_object_dict(self, presentation, raw, value, context):
        if not isinstance(value, dict):
            raise InvalidValueError(u'{0} is not a dict: {1}'
                                    .format(self.full_name, safe_repr(value)),
                                    locator=self.get_locator(raw))
        return FrozenDict(((k, self.cls(name=k, raw=v, container=presentation))
                           for k, v in value.iteritems()))

    def _dump_object_dict(self, context, value):
        puts(u'{0}:'.format(self.name))
        with context.style.indent():
            for v in value.itervalues():
                if hasattr(v, '_dump'):
                    v._dump(context)

    # sequenced object list

    def _get_sequenced_object_list(self, presentation, raw, value, context):
        if not isinstance(value, list):
            raise InvalidValueError(u'{0} is not a sequenced list (a list of dicts, '
                                    u'each with exactly one key): {1}'
                                    .format(self.full_name, safe_repr(value)),
                                    locator=self.get_locator(raw))
        sequence = []
        for v in value:
            if not isinstance(v, dict):
                raise InvalidValueError(u'{0} list elements are not all dicts with '
                                        u'exactly one key: {1}'
                                        .format(self.full_name, safe_repr(value)),
                                        locator=self.get_locator(raw))
            if len(v) != 1:
                raise InvalidValueError(u'{0} list elements do not all have exactly one key: {1}'
                                        .format(self.full_name, safe_repr(value)),
                                        locator=self.get_locator(raw))
            key, value = v.items()[0]
            sequence.append((key, self.cls(name=key, raw=value, container=presentation)))
        return FrozenList(sequence)

    def _dump_sequenced_object_list(self, context, value):
        puts(u'{0}:'.format(self.name))
        for _, v in value:
            if hasattr(v, '_dump'):
                v._dump(context)

    # primitive dict for unknown fields

    def _get_primitive_dict_unknown_fields(self, presentation, raw, context):
        if isinstance(raw, dict):
            primitive_dict = raw
            if self.cls is not None:
                if context is None:
                    context = Field._get_context()
                primitive_dict = OrderedDict()
                for k, v in raw.iteritems():
                    if k not in presentation.FIELDS:
                        if v is None:
                            v = NULL
                        try:
                            primitive_dict[k] = self._coerce_primitive(v, context)
                        except ValueError as e:
                            raise InvalidValueError(u'{0} is not a dict of "{1}" values:'
                                                    u' entry "{2}" is {3}'
                                                    .format(self.full_name, self.full_cls_name,
                                                            k, safe_repr(v)),
                                                    locator=self.get_locator(raw),
                                                    cause=e)
            return FrozenDict(primitive_dict)
        return None

    def _dump_primitive_dict_unknown_fields(self, context, value):
        self._dump_primitive_dict(context, value)

    # object dict for unknown fields

    def _get_object_dict_unknown_fields(self, presentation, raw, context):
        if isinstance(raw, dict):
            return FrozenDict(((k, self.cls(name=k, raw=v, container=presentation))
                               for k, v in raw.iteritems() if k not in presentation.FIELDS))
        return None

    def _dump_object_dict_unknown_fields(self, context, value):
        self._dump_object_dict(context, value)
