"""This module contains export views for the ``translation`` app."""

import os
import polib

from openpyxl.formatting import CellIsRule

from django.conf import settings
from django.views.generic.base import TemplateView
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView

from mtp.apps.common.utils import remove_ponctuation
from mtp.apps.common.views_utils import RestrictToSuperuserOrTrainerMixin
from mtp.apps.import_export.stylexlsx import StyleXlsx
from mtp.apps.import_export.views import XLSExportViewMixin
from mtp.apps.trainings.resources import TrainingResource

from ..constants import ACTIVITIES_TO_TRANSLATE, CELL_TITLE, NO_TRANSLATION, PO_HEADERS
from .mixins import TranslationExportViewMixin


class POExportView(XLSExportViewMixin, RestrictToSuperuserOrTrainerMixin, TemplateView):
    """This view allows to extract translation in po file to a xlsxfile."""

    title = 'Interface'

    @property
    def get_language_code(self):
        """Get selected language code passed in parameters url.

        Returns
        -------
        str
            The selected language code.
        """
        return self.kwargs['language_code_slug']

    @property
    def get_headers(self):
        """Get headers to display according the selected language.

        Returns
        -------
        headers : list[str]
            The headers to display in sheet.
        """
        headers = PO_HEADERS.copy()
        headers[3] += ' [' + self.get_language_code + ']'
        headers[5] += ' [' + self.get_language_code + ']'
        return headers

    def create_sheets(self, context):  # pylint: disable=unused-argument
        """Create sheets of export file. We create a sheet for each interface : CMS + iOS.

        Parameters
        ----------
        context : dict
            Data computed in ``get_context_data`` that may be useful to create the doc.

        """

        sheet_name = self.writer.first_sheet_name
        sheet_name = self.writer.initialize(sheet_name, 'CMS')
        po_file = self.get_po_file(self.get_language_code, 'django')
        po_file_en = self.get_po_file(settings.LANGUAGE_CODE, 'django')
        self.export_data(sheet_name, po_file, po_file_en)

        sheet = self.writer.create_new_sheet('iOS')
        self.writer.initialize(sheet.title)
        po_file = self.get_po_file(self.get_language_code, 'client')
        po_file_en = self.get_po_file(settings.LANGUAGE_CODE, 'client')
        self.export_data(sheet.title, po_file, po_file_en)

    def get_po_file(self, language, domain):
        """Provide a .po file with polib.

        Parameters
        ----------
        language : str
            The language wanted.
        domain : str
            The domain or pofile name wanted.
            The domain is ``django`` for CMS and ``client`` for iOS.

        Raises
        ------
        ValueError
            If there is no translation file according to these provided parameters.

        Returns
        -------
        pofile
            The correspondent .po file loaded with polib.
        """
        # management.call_command("makemessages", "--no-location", locale=[language])
        # management.call_command("makemessagesios", language)

        locale_path = settings.LOCALE_PATHS[0]
        file_path = language + '/LC_MESSAGES/' + domain + '.po'
        file_path = os.path.join(locale_path, file_path)
        if not os.path.isfile(file_path):
            raise ValueError("No %s traduction exists for this language" % domain)
        return polib.pofile(file_path)

    def apply_color_condition(self, text):
        """Find the color condition to apply to provided text.

        If text is empty, we return a template text equals to NO_TRANSLATION constant.

        Parameters
        ----------
        text : str
            The text which is evaluated.

        Returns
        -------
        color_conditions : openpyxl ``CellIsRule``
            The color conditions to apply.
            RED if text is empty. Else GREEN.
        text_to_translate : str
            The text to translate.
        """
        color_conditions = []
        style = StyleXlsx()
        if text == '':
            text_to_translate = NO_TRANSLATION
            color_conditions += [CellIsRule(operator='equal', formula=['"%s"' % NO_TRANSLATION],
                                            stopIfTrue=True, font=style.RED_FONT)]
        else:
            text_to_translate = text.replace("\"", "\'").replace("&nbsp;", " ")
            color_conditions += [CellIsRule(operator='equal',
                                            formula=['"%s"' % text_to_translate],
                                            stopIfTrue=True, font=style.GREEN_FONT)]
        return color_conditions, text_to_translate

    def convert_po_to_excel(self, sheet_name, po_file, po_file_en):
        """Convert a po file to xlsx file.

        Write po file in provided sheet with sheet_name.

        Parameters
        ----------
        sheet_name : str
            The name of sheet which will be edited.
        po_file : pofile
            The po file in wanted language.
        po_file_en : pofile
            The po file in english language : reference text.
        """
        rows = []
        valid_entries = [entry for entry in po_file if not entry.obsolete]
        for entry in valid_entries:
            trad_en = po_file_en.find(entry.msgid)
            trad_en = trad_en.msgstr

            if trad_en == '':
                trad_en = ' '

            if entry.msgid_plural:
                conditions1, text1 = self.apply_color_condition(entry.msgstr_plural[0])
                conditions2, text2 = self.apply_color_condition(entry.msgstr_plural[1])
                row = [
                    {'value': trad_en, 'style': 'PROTECTED_DEFAULT_TABLE'},
                    {'value': entry.msgctxt, 'style': 'PROTECTED_DEFAULT_TABLE'},
                    {'value': entry.msgid, 'style': 'PROTECTED_DEFAULT_TABLE'},
                    {'value': text1, 'style': 'EDITABLE_DEFAULT_TABLE', 'conditions': conditions1},
                    {'value': entry.msgid_plural, 'style': 'PROTECTED_DEFAULT_TABLE'},
                    {'value': text2, 'style': 'EDITABLE_DEFAULT_TABLE', 'conditions': conditions2}
                ]
            else:
                conditions, text = self.apply_color_condition(entry.msgstr)
                row = [
                    {'value': trad_en, 'style': 'PROTECTED_DEFAULT_TABLE'},
                    {'value': entry.msgctxt, 'style': 'PROTECTED_DEFAULT_TABLE'},
                    {'value': entry.msgid, 'style': 'PROTECTED_DEFAULT_TABLE'},
                    {'value': text, 'style': 'EDITABLE_DEFAULT_TABLE', 'conditions': conditions},
                    {'value': '', 'style': 'PROTECTED_DEFAULT_TABLE'},
                    {'value': '', 'style': 'PROTECTED_DEFAULT_TABLE'}
                ]
            rows.append(row)
        self.writer.write_rows(rows, sheet_name)

    def export_data(self, sheet_name, po_file, po_file_en):
        """Export po file translation with this correspondent in english.

        Parameters
        ----------
        sheet_name : str
            The name of sheet which will be edited.
        po_file : pofile
            The po file in wanted language.
        po_file_en : pofile
            The po file in english language : reference text.
        """
        row = self.writer.create_headers(self.get_headers)
        self.writer.write_row(row, sheet_name)
        self.convert_po_to_excel(sheet_name, po_file, po_file_en)


class TranslationExportDetailView(TranslationExportViewMixin, DetailView):
    """This view allows to export text to translate for an object."""

    def create_sheets(self, context):  # pylint: disable=unused-argument
        """Creation of a single sheet.

        Parameters
        ----------
        context : dict
            Data computed in ``get_context_data`` that may be useful to create the doc.

        """

        self.writer.cell_title = CELL_TITLE
        sheet_name = self.writer.first_sheet_name
        self.object = self.get_object()  # pylint: disable=attribute-defined-outside-init
        title = remove_ponctuation(str(self.get_parent(self.object)))
        sheet_name = self.writer.initialize(sheet_name, title)
        self.export_data(sheet_name, self.object)


class TranslationExportListView(TranslationExportViewMixin, ListView):
    """This view allows to export text to translate for an objects list."""

    def create_sheets(self, context):  # pylint: disable=unused-argument
        """Creation of a sheet for each object in the list.

        Parameters
        ----------
        context : dict
            Data computed in ``get_context_data`` that may be useful to create the doc.

        """

        self.writer.cell_title = CELL_TITLE
        self.writer.remove_all_sheet()
        for item in self.get_queryset():
            item_name = remove_ponctuation(str(self.get_parent(item)))
            sheet = self.writer.create_new_sheet(item_name)
            self.writer.initialize(sheet.title)
            self.export_data(sheet.title, item)


class ActivityTranslationExportView(TranslationExportDetailView):
    """This view allows to export text to translate for a training and this activities."""

    resource = TrainingResource
    pk_url_kwarg = 'training_uuid'

    @property
    def get_title(self):
        return remove_ponctuation(str(self.get_object()))

    def get_activities(self):
        """Get activities to export."""
        activities = []
        for activity in ACTIVITIES_TO_TRANSLATE:
            activity_model = activity.get('model')
            activities += activity_model.objects.filter(training=self.object, is_deleted=False)
        return activities

    def create_sheets(self, context):  # pylint: disable=unused-argument
        """Creation of a sheet for each activities.

        Parameters
        ----------
        context : dict
            Data computed in ``get_context_data`` that may be useful to create the doc.

        """

        self.writer.cell_title = CELL_TITLE
        sheet_name = self.writer.first_sheet_name
        self.object = self.get_object()  # pylint: disable=attribute-defined-outside-init
        title = remove_ponctuation(str(self.get_parent(self.object)))
        sheet_name = self.writer.initialize(sheet_name, title)
        self.export_data(sheet_name, self.object, enable_nested=False)
        for activity in self.get_activities():
            activity_name = remove_ponctuation(str(self.get_parent(activity)))
            sheet = self.writer.create_new_sheet(activity_name)
            self.writer.initialize(sheet.title)
            self.export_data(sheet.title, activity)
