"""This module provides the abstract ``IdeasActivity`` and ``Idea`` models for the ``ideas`` app"""

import pandas as pd

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

from django_extensions.db.models import TimeStampedModel
from orderable.models import Orderable

from mtp.apps.data_export.constants import EXCEL_STYLE_CHOICES
from mtp.apps.data_export.exporters import ExcelDataExporter
from mtp.apps.likes.models import Likeable
from mtp.apps.trainings.models import ResultsToExcelActivityMixin, TrainingSession


class IdeasActivity(ResultsToExcelActivityMixin, models.Model):
    """Django abstract model defining the base fields for the ``IdeasActivity`` models

    Attributes
    ----------
    is_anonymous: django ``BooleanField``, default to False
        If True, the authors of the ``Ideas`` of this activity won't be displayed.

    Notes
    -----
    This model is abstract

    """

    is_anonymous = models.BooleanField(
        default=False,
        verbose_name=_('Anonymous')
    )

    class Meta:
        abstract = True

    def is_exportable(self, session):
        """Test that this idea activity results are exportable to excel

        An idea activity is exportable to excel if:
        - It contains at least one trainee idea

        Parameters
        ----------
        For the parameters, see ``ResultsToExcelActivityMixin``

        """

        return self.ideas.filter(session=session).non_deleted().count() > 0

    def results_to_excel(self, session, path=None):
        """Get the session results of this idea activity as an excel file

        For the parameters, see ``ResultsToExcelActivityMixin``

        """

        excel_exporter = ExcelDataExporter(path)

        excel_data = self.get_results_excel_data(session)
        excel_data['sheet_name'] = self.name
        excel_exporter.add_sheet(**excel_data)

        return excel_exporter.save()

    def get_results_excel_data(self, session):
        """Get the results data of this idea activity for a given session

        Parameters
        ----------
        session: TrainingSession
            The training session we want the results for

        Returns
        -------
        dict
            A dict containing the parameters for the ``ExcelDataExporter.add_sheet``

        """

        # Fetch the ideas related to this idea activity
        ideas = self.ideas.for_session(session).non_deleted().order_by('created')

        # Build the columns of the data frame
        columns = [
            str(_('Likes')),
            str(_('Author first name')),
            str(_('Author last name')),
        ]

        header_styles = [EXCEL_STYLE_CHOICES.HEADER] * len(columns)

        data_frame = pd.DataFrame(columns=columns)

        # For each idea, populate a row of the data frame
        for index, idea in enumerate(ideas):
            idea_data = [
                idea.likes.non_deleted().count(),
                idea.user.first_name if idea.user else '',
                idea.user.last_name if idea.user else ''
            ]

            # The text of the idea is the index
            index_name = '%d - %s' % (
                index,
                idea.text
            )

            data_frame.loc[index_name] = idea_data

        return {
            'data': data_frame,
            'header_styles': header_styles,
            'freeze_panes': [1, 0]
        }


class Idea(Likeable, Orderable, TimeStampedModel):
    """Django abstract model defining the base fields for the ``Idea`` models

    Attributes
    ----------
    user: django ``ForeignKey`` field to ``settings.AUTH_USER_MODEL``
        The author of this idea
    session: django ``ForeignKey`` field to ``TrainingSession``, Nullable
        The session this idea was made into.

    Notes
    -----
    This model is abstract

    """

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        related_name='%(class)s_ideas',
        null=True,
        blank=True,
        verbose_name=_('User'),
        on_delete=models.CASCADE
    )
    session = models.ForeignKey(
        TrainingSession,
        related_name='%(class)s_ideas',
        verbose_name=_('Session'),
        null=True,
        blank=True,
        on_delete=models.CASCADE
    )

    class Meta:
        abstract = True
