from __future__ import unicode_literals

from datetime import datetime

from django.contrib.auth import get_user_model
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext as _
from django_core.db.models import AbstractTokenModel
from django_core.db.models.mixins.base import AbstractBaseModel
from django_core.utils.list_utils import make_obj_list

from .constants import Status
from .db.models import ShareManager
from django.conf import settings



class AbstractShare(AbstractTokenModel, AbstractBaseModel):
    """Abstract Base share object represents basic shared information for a
    specific user sharing an object.

    It's highly recommended that the implementing class puts a index on one of
    the two options:

    * object_id
    * (object_id, content_type)

    Fields:
    * for_user: the user the object is shared with. This is optional since the
        user might not exist yet.
    * email: email of the user who the share was sent to if user is unknown.
    * first_name: first name of the person invited
    * last_name: last name of the person invited
    * last_sent: date time the share was last sent.
    * message: message sent to user in email.
    * status: status of the share (PENDING, ACCEPTED, DECLINED, etc)
    * response_dttm: the datetime the share was responded.
    * content_type: the content type of the generic shared object
    * object_id: the object id of the shared object
    * shared_object: the object being shared.
    * token: unique share token.

    """
    for_user = models.ForeignKey(settings.AUTH_USER_MODEL,
                                 blank=True,
                                 null=True,
                                 related_name='for_user+')
    email = models.EmailField(blank=True, null=True, db_index=True,
                              help_text=_('Email address of the person you '
                                          'want to share with.'))
    first_name = models.CharField(max_length=100, blank=True, null=True)
    last_name = models.CharField(max_length=100, blank=True, null=True)
    last_sent = models.DateTimeField(default=datetime.utcnow)
    message = models.TextField(blank=True, null=True)
    status = models.CharField(max_length=25,
                              default=Status.PENDING,
                              choices=Status.CHOICES)
    response_dttm = models.DateTimeField(blank=True, null=True)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    shared_object = generic.GenericForeignKey('content_type', 'object_id')
    objects = ShareManager()

    class Meta:
        abstract = True

    @classmethod
    def save_prep(cls, instance_or_instances):
        """Preprocess the object before the object is saved.  This
        automatically gets called when the save method gets called.
        """
        instances = make_obj_list(instance_or_instances)

        for instance in instances:

            if not instance.is_pending() and not instance.response_dttm:
                instance.response_dttm = datetime.utcnow()

        return super(AbstractShare, cls).save_prep(
                                            instance_or_instances=instances)

    def is_accepted(self):
        """Boolean indicating if the share is accepted."""
        return self.status == Status.ACCEPTED

    def is_pending(self):
        """Boolean indicating if the share is pending."""
        return self.status == Status.PENDING

    def is_declined(self):
        return self.status == Status.DECLINED

    def is_inactive(self):
        return self.status == Status.INACTIVE