"""This module provides the ``TrainingActivity`` model for the ``trainings`` app"""

from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext_lazy as _

from mtp.discrete_apps.versionable.models import Dependency, PolymorphicModelForDependency

from mtp.apps.assessments.models import AssessableActivity
from mtp.apps.common.models import NonAbstractChildOrderable
from mtp.apps.common.utils import bypass_orderable, classproperty
from mtp.apps.sync.models import Syncable

from .. import constants
from ..managers import DependencyTrainingActivityManager


class TrainingActivity(AssessableActivity, Dependency, Syncable, NonAbstractChildOrderable,
                       PolymorphicModelForDependency):
    """Base (non-abstract) Django model representing a training activity.

    Attributes
    ----------
    training : django ``ForeignKey`` field
        The training the activity belong to.
    name : django ``CharField``
        The name of the activity, mandatory.
    description : django ``TextField``
        Optional description for this activity.

    Notes
    -----
    This model is a ``Dependency`` of the ``Training``.

    """
    training = models.ForeignKey(
        'Training',
        verbose_name=_("training"),
        related_name='activities'
    )

    name = models.CharField(max_length=255, verbose_name=_("name"))
    description = models.TextField(
        blank=True,
        verbose_name=_('Description')
    )

    needs_approval = models.BooleanField(
        default=False,
        verbose_name=_("needs trainer approval"),
        help_text=_("Does the activity needs a trainer approval to be started?")
    )

    non_lockable_fields = Dependency.non_lockable_fields + Syncable.non_lockable_fields

    objects = DependencyTrainingActivityManager()

    class Meta:
        unique_together = ('sort_order', 'training')

    @classproperty
    def versionable_link(cls):  # pylint: disable=no-self-argument
        """Defines the link the the ``Versionable`` object"""

        from . import Training
        return Training, 'training'

    def __str__(self):
        return self.name

    def duplicate(self, **kwargs):
        """Override the ``duplicate`` from the ``Dependency``.

        We don't want the training to be duplicated when we duplicate an activity.

        For the parameters, see ``mtp.discrete_apps.duplicable.models.Duplicable``

        See also
        --------
        mtp/discrete_apps/duplicable/README.rst

        """

        with bypass_orderable():
            return super().duplicate(non_duplicable_relations={'training'}, **kwargs)

    def get_duplicate_url(self):
        """Get the url to duplicate the activity

        Returns
        -------
        string
            The wanted url.

        """
        return reverse('trainings:activity-duplicate', kwargs={
            'activity_uuid': self.pk, 'training_uuid': self.training.pk})

    def get_delete_url(self):
        """Get the url to soft-delete the activity

        Returns
        -------
        string
            The wanted url.

        """
        return reverse('trainings:activity-delete', kwargs={
            'activity_uuid': self.pk, 'training_uuid': self.training.pk})

    def get_qrcode_data(self):
        """Get data will be stored in the QRCode to launch an activity.

        Returns
        -------
        dict
            Data to insert in the QRCode.

        """
        activity_type = getattr(constants.MODULE_CHOICES, self.__class__.__name__.upper())

        # When the activity is an original version, we return its id in `original_version` property.
        # This hack allow to keep compatibilities with old iPad versions.

        data = {
            'id': self.id,
            'original_version': self.original_version_id or self.id,
            'type': activity_type,
            'action': constants.ACTIVITY_LAUNCH_ACTION
        }

        return data

    def get_qrcode_url(self):
        """Get the url to download the QRCode able to launch activity.

        Returns
        -------
        string
            The wanted url.

        """
        return reverse(
            'trainings:download-launch-qrcode-detail',
            kwargs={
                'activity_uuid': self.pk,
                'training_uuid': self.training.pk
            }
        )
