from functools import wraps
import logging

from .. import exceptions, schema
from ..fields import PlainField, RelatedField

from .base import SavableDomainObject, CreatableDomainObjectList
from .registry import domain_objects, domain_object_lists


__all__ = (
    'Event', 'EventList',
)


logger = logging.getLogger(__name__)


def returns(type_):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            return type_(func(*args, **kwargs))
        return wrapper
    return decorator


@domain_objects.register
class Event(SavableDomainObject):
    model_class = 'achievery.Event'

    comment = PlainField(schema_type=schema.TYPE.STRING)
    is_active = PlainField(schema_type=schema.TYPE.BOOLEAN)
    is_hidden = PlainField(schema_type=schema.TYPE.BOOLEAN)
    level = PlainField(schema_type=schema.TYPE.NUMBER)
    revision = PlainField(schema_type=schema.TYPE.NUMBER)
    slot = PlainField(schema_type=schema.TYPE.NUMBER, null=True)
    given = RelatedField(related_class='GivenAchievement', name='given_achievement')
    initiator = RelatedField(related_class='Person')
    happened_at = PlainField(name='created_at', schema_type=schema.TYPE.STRING)

    @property
    def previous(self):
        try:
            # noinspection PyUnresolvedReferences
            res = (
                self.given.events.exclude(id=self.id).order_by('-revision')[0]
            )
        except (exceptions.DoesNotExist, IndexError):
            res = None

        return res

    @property
    def is_unlocked(self):
        return self.previous is None

    @property
    @returns(bool)
    def is_levelup(self):
        return self.previous and self.previous.level < self.level

    @property
    @returns(bool)
    def is_leveldown(self):
        return self.previous and self.previous.level > self.level

    @property
    @returns(bool)
    def is_taken_away(self):
        return self.previous and self.previous.is_active > self.is_active

    @property
    @returns(bool)
    def is_returned(self):
        return self.previous and self.previous.is_active < self.is_active


@domain_object_lists.register
class EventList(CreatableDomainObjectList):
    domain_object_class = Event
