"""This module contains the ``DiscoverItem``, to expose a functionality to the user"""

from django.contrib.postgres.fields import IntegerRangeField
from django.db import models
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _

from extended_choices.choices import Choices

from .fields import LanguageField
from .managers import DiscoverItemManager


class DiscoverItem(models.Model):
    """Model to display an introduction to a given feature

    Attributes
    ----------
    TAG_CHOICES: ``Choices``
        A list of available tags
    CATEGORY_CHOICES: ``Choices``
        A list of available categories

    language: django ``LanguageField``
        The language of the current discover item

    is_active: django ``BooleanField``
        Is the  current discover item is active or not ?

    title: django ``CharField``
        The title of the current discover item
    slug: django ``SlugField``
        The slug of the current discover item
    image: django ``ImageField``
        The image of the current discover item
    short_description: django ``CharField``
        A short description of the current discover item
    long_description: django ``TextField``
        The complete description of the current discover item

    link_title: django ``CharField``
        The title of the link of this discover item
    link_url: django ``CharField``
        The url of the link of this discover item

    tag: django ``CharField``
        A tag for the current discover item, contains one of the ``TAG_CHOICES``
    category: django ``CharField``
        A category for the current discover item, contains one of the ``CATEGORY_CHOICES``

    major_versions: django ``IntegerRangeField``
        The major versions range for this discover item to be displayed
    minor_versions: django ``IntegerRangeField``
        The minor versions range for this discover item to be displayed
    hotfix_versions: django ``IntegerRangeField``
        The hotfix versions range for this discover item to be displayed

    created_at: django ``DateTimeField``
        The date and time of the creation of this discover item
    updated_at: django ``DateTimeField``
        The date and time of the last update of this discover item

    """

    TAG_CHOICES = Choices(
        ('NEW', 'new', _('New')),
        ('IMPORTANT', 'important', _('Important')),
    )

    CATEGORY_CHOICES = Choices(
        ('RESOURCES', 'resources', _('Resources')),
        ('SESSIONS', 'sessions', _('Sessions')),
        ('USERS', 'users', _('Users')),
    )

    is_active = models.BooleanField(
        default=True,
        verbose_name=_('Is active'),
    )

    language = LanguageField(
        verbose_name=_('Language'),
        help_text=_('The language of this discover item')
    )

    title = models.CharField(
        max_length=30,
        verbose_name=_('Title')
    )
    slug = models.SlugField(
        max_length=500,
        verbose_name=_('Slug')
    )
    image = models.ImageField(
        verbose_name=_('Image'),
        upload_to='django_discover'
    )
    short_description = models.CharField(
        max_length=80,
        verbose_name=_('Short description')
    )
    long_description = models.TextField(
        verbose_name=_('Long description')
    )

    link_title = models.CharField(
        max_length=50,
        verbose_name=_('Link title'),
        null=True,
        blank=True
    )
    link_url = models.CharField(
        max_length=500,
        verbose_name=_('Link url'),
        null=True,
        blank=True
    )

    tag = models.CharField(
        max_length=20,
        choices=TAG_CHOICES,
        verbose_name=_('Tag'),
        null=True,
        blank=True
    )
    category = models.CharField(
        max_length=20,
        choices=CATEGORY_CHOICES,
        verbose_name=_('Category'),
        null=True,
        blank=True
    )

    major_versions = IntegerRangeField(
        verbose_name=_('Major version range'),
        null=True,
        blank=True
    )
    minor_versions = IntegerRangeField(
        verbose_name=_('Minor version range'),
        null=True,
        blank=True
    )
    hotfix_versions = IntegerRangeField(
        verbose_name=_('Hotfix version range'),
        null=True,
        blank=True
    )

    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name=_('Date and time of creation'),
    )
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name=_('Date and time of the last update'),
    )

    objects = DiscoverItemManager()

    class Meta:
        unique_together = (('language', 'slug'),)

    def __str__(self):
        return '[%(language)s] %(slug)s <%(from_version)s - %(until_version)s>' % {
            'language': self.language,
            'slug': self.slug,
            'from_version': self.from_version,
            'until_version': self.until_version
        }

    @cached_property
    def from_version(self):
        """Get the full version number from this item should be displayed

        Returns
        -------
        str

        """

        def version_lower_part_to_string(version):
            """Make the lower bound of the version part to a string

            Parameters
            ----------
            version: IntegerRangeField

            Returns
            -------
            str
                The lower version of the given part
                or '*'

            """

            if version and version.lower:
                return version.lower

            return '*'

        return '%s.%s.%s' % (
            version_lower_part_to_string(self.major_versions),
            version_lower_part_to_string(self.minor_versions),
            version_lower_part_to_string(self.hotfix_versions)
        )

    @cached_property
    def until_version(self):
        """Get the full version number until this item should not be displayed

        Returns
        -------
        str

        """

        def version_upper_part_to_string(version):
            """Make the upper bound of the version part to a string

            Parameters
            ----------
            version: IntegerRangeField

            Returns
            -------
            str
                The upper version of the given part
                or '*'

            """

            if version and version.upper:
                return version.upper

            return '*'

        return '%s.%s.%s' % (
            version_upper_part_to_string(self.major_versions),
            version_upper_part_to_string(self.minor_versions),
            version_upper_part_to_string(self.hotfix_versions),
        )
