"""This module contains the models of the ``enventlog`` app"""

from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _

from django_extensions.db.fields import UUIDField
from django_extensions.db.fields.json import JSONField

from extended_choices import Choices

from mtp.apps.sync.models import Syncable


# These constants enumerate all the actions that can be tracked in the event
# log. Their semantics should be made fairly self-explanatory by the textual
# descriptions in `ACTION_CHOICES`.

ACTION_CHOICES = Choices(
    ('APP_LOGIN', 'cms_login', _("User logged into the CMS")),
    ('CMS_LOGIN', 'app_login', _("User logged into the iOS app")),
    ('SESSION_CREATE', 'session_create', _("User created a session")),
    ('SESSION_REGISTER', 'session_register', _("User was registered for a session")),
    ('SESSION_START', 'session_start', _("User started a session")),
    ('SESSION_JOIN', 'session_join', _("User joined a session")),
    ('SESSION_QUIT', 'session_quit', _("User quit a session")),
    ('DOCUMENT_DOWNLOAD', 'document_download', _("User downloaded a document")),
)


class EventLog(Syncable):
    """This model lets us keep track of the usage history of the application.

    This gives us a convenient and standardized way to compute usage statistics.

    Attributes
    ----------
    created_at: django ``DateTimeField``
        The creation date of the event
    action: django ``CharField``
        The normalized string describing the logged action, one of ``ACTION_CHOICES``
    subject: django ``GenericForeignKey``
        The object instance the event happened on
    source: django ``GenericForeignKey``
        The initiator of the event, in the majority of the cases, a user / trainer
    target: django ``GenericForeignKey``
        The target instance, ex: A `user` (subject) added to a `session` (target)
    extra: django ``JSONField``
        Contains additional data about this event

    """

    created_at = models.DateTimeField(default=timezone.now, db_index=True)
    action = models.CharField(max_length=64, choices=ACTION_CHOICES,
                              db_index=True)

    subject_type = models.ForeignKey(
        ContentType,
        related_name='events_on',
        on_delete=models.CASCADE
    )
    subject_pk = UUIDField()
    subject = GenericForeignKey('subject_type', 'subject_pk')

    source_type = models.ForeignKey(
        ContentType,
        blank=True,
        null=True,
        related_name='events_from',
        on_delete=models.CASCADE
    )
    source_pk = UUIDField(blank=True, null=True)
    source = GenericForeignKey('source_type', 'source_pk')

    target_type = models.ForeignKey(
        ContentType,
        blank=True,
        null=True,
        related_name='events_to',
        on_delete=models.CASCADE
    )
    target_pk = UUIDField(blank=True, null=True)
    target = GenericForeignKey('target_type', 'target_pk')

    extra = JSONField(blank=True)

    class Meta:
        ordering = ('-created_at',)

    def __str__(self):
        return 'Event #%s - %s - %s' % (self.id, self.action, self.subject)
