"""This module holds the models of the ``themes`` app."""

from django.conf import settings
from django.db import models
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _

from django_hashable_file_fields.hashers import with_default
from django_hashable_file_fields.models import HashableFileFieldsBaseModel

from mtp.apps.common.constants import RESOLUTIONS
from mtp.apps.common.utils import mod_lazy
from mtp.apps.sync.models import Syncable
from mtp.apps.themes.managers import ThemeManager

from . import constants


class Theme(HashableFileFieldsBaseModel, Syncable):
    """Django model representing a theme.

    A theme is composed by a set of colors and images, allowing the customization of the look
    of the front-end applications and the cms.

    """

    class Meta:
        ordering = ("-default", "name")

    name = models.CharField(max_length=200)
    default = models.BooleanField(default=False)

    # "Old" fields, to be deprecated.
    color_first = models.CharField(max_length=10, default=settings.THEME_COLOR_FIRST)
    color_second = models.CharField(max_length=10, default=settings.THEME_COLOR_SECOND)
    color_item = models.CharField(max_length=10, default=settings.THEME_COLOR_ITEM)
    color_selected_item = models.CharField(
        max_length=10,
        default=settings.THEME_COLOR_SELECTED_ITEM)
    color_text_item = models.CharField(max_length=10, default=settings.THEME_COLOR_TEXT_ITEM)
    color_text_selected_item = models.CharField(
        max_length=10,
        default=settings.THEME_COLOR_TEXT_SELECTED_ITEM)
    color_text_quizz = models.CharField(max_length=10, default=settings.THEME_COLOR_TEXT_QUIZZ)
    background_color = models.CharField(max_length=10, default=settings.THEME_BACKGROUND_COLOR)
    background_color_diffusion = models.CharField(
        max_length=10,
        default=settings.THEME_BACKGROUND_COLOR_DIFFUSION)

    background_image = models.ImageField(
        upload_to="training",
        blank=True,
        default=settings.THEME_BACKGROUND_IMAGE)
    background_image_hash = models.CharField(max_length=36, blank=True, null=True)
    background_image_diffusion = models.ImageField(
        upload_to="training",
        blank=True,
        default=settings.THEME_BACKGROUND_IMAGE_DIFFUSION)
    background_image_diffusion_hash = models.CharField(max_length=36, blank=True, null=True)

    # "New" fields.
    main = models.CharField(max_length=64, blank=True)
    main_lighter = models.CharField(max_length=64, blank=True)
    main_darker = models.CharField(max_length=64, blank=True)

    complementary = models.CharField(max_length=64, blank=True)

    clear = models.CharField(max_length=64, blank=True)

    background = models.CharField(max_length=64, blank=True)

    gray = models.CharField(max_length=64, blank=True, default=settings.THEME_GRAY_COLOR)
    gray_lighter = models.CharField(max_length=64, blank=True)
    gray_darker = models.CharField(max_length=64, blank=True)

    text_on_main = models.CharField(max_length=64, blank=True)
    text_on_main_lighter = models.CharField(max_length=64, blank=True)
    text_on_main_darker = models.CharField(max_length=64, blank=True)
    text_on_complementary = models.CharField(max_length=64, blank=True)
    text_on_clear = models.CharField(max_length=64, blank=True)

    accent_blue = models.CharField(max_length=64, blank=True)
    accent_green = models.CharField(max_length=64, blank=True)
    accent_yellow = models.CharField(max_length=64, blank=True)
    accent_pink = models.CharField(max_length=64, blank=True)
    accent_red = models.CharField(max_length=64, blank=True)
    accent_white = models.CharField(max_length=64, blank=True)

    font_name = models.CharField(max_length=64, blank=True)
    font_bold_name = models.CharField(max_length=64, blank=True)
    font_thin_name = models.CharField(max_length=64, blank=True)

    brand_logo = models.ImageField(
        upload_to='theme',
        help_text=_('Choose a logo which represents your brand. '
                    'This logo is displayed in the top left corner in the cms'),
        verbose_name=_('brand logo'),
        blank=True,
        default=constants.DEFAULT_BRAND_LOGO_PATH
    )

    header_image = models.ImageField(
        upload_to="training",
        help_text=mod_lazy(_('Preferred size: %(retina_width)dx%(retina_height)dpx (Retina) '
                             'or %(normal_width)dx%(normal_height)dpx (Normal)'), **RESOLUTIONS),
        verbose_name=_('Header Image'),
        blank=True,
        default=settings.THEME_HEADER_IMAGE)
    header_image_hash = models.CharField(_('Header Image Hash'), max_length=64, blank=True)

    reveal_logo = models.ImageField(
        upload_to='theme',
        help_text=_('Choose a logo which be used in reveal. '),
        verbose_name=_('reveal logo'),
        blank=True,
        null=True,
        default=constants.DEFAULT_REVEAL_LOGO_PATH
    )
    reveal_logo_hash = models.CharField(_('Reveal Logo Hash'), max_length=64, blank=True)

    home_diffusion_image = models.ImageField(upload_to="training",
                                             verbose_name=_('Home Diffusion Image'),
                                             blank=True,
                                             default=settings.THEME_HOME_DIFFUSION_IMAGE)
    home_diffusion_image_hash = models.CharField(_('Home Diffusion Image Hash'),
                                                 max_length=64, blank=True)

    favicon = models.ImageField(
        upload_to='theme/favicon',
        blank=True,
        default=constants.DEFAULT_FAVICON_PATH,
    )

    hashable_fields = [
        (field_name, '%s_hash' % field_name, with_default(settings.EMPTY_FILE_HASH))
        for field_name
        in [
            'background_image',
            'background_image_diffusion',
            'header_image',
            'reveal_logo',
            'home_diffusion_image',
        ]
    ]

    objects = ThemeManager()

    sync_files_to_master = True

    @property
    def instance_name(self):
        """The name of the current instance.

        Returns
        -------
        string
            The instance name.

        """

        return settings.INSTANCE_NAME

    def __str__(self):
        return self.default and "%s (%s)" % (self.name, _("default")) or self.name

    def compute_hashable_fields(self):
        """Set default value for some images before computing their hash"""

        if not self.brand_logo:
            self.brand_logo = constants.DEFAULT_BRAND_LOGO_PATH

        if not self.favicon:
            self.favicon = constants.DEFAULT_FAVICON_PATH

        if not self.reveal_logo:
            self.reveal_logo = constants.DEFAULT_REVEAL_LOGO_PATH

        super().compute_hashable_fields()

    def save(self, *args, **kwargs):
        if self.default:
            # We cannot use ``update`` because it does not call the ``save`` method and the
            # ``Syncable`` models need to call the ``save`` method for each update.
            for theme in Theme.objects.filter(default=True):
                if theme.pk == self.pk:
                    continue
                theme.default = False
                theme.save()

        super(Theme, self).save(*args, **kwargs)

    @cached_property
    def media_files(self):
        """Get the list of media file paths for this theme

        Returns
        -------
        list(str)
            A list of media relative paths for this theme

        """

        return [
            self.background_image.name,
            self.background_image_diffusion.name,
            self.header_image.name,
            self.home_diffusion_image.name,
            self.favicon.name,
        ]
