# -*- mode: python -*-
# -*- coding: utf-8 -*-

##############################################################################
#
# Gestion scolarite IUT
#
# Copyright (c) 1999 - 2023 Emmanuel Viennet.  All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#   Emmanuel Viennet      emmanuel.viennet@gmail.com
#
##############################################################################

"""Generation bulletins de notes dans l'ancien format de ScoDoc (avant juillet 2011).

 Code partiellement redondant, copié de l'ancien système de gestion des bulletins.

 Voir sco_bulletins_standard pour une version plus récente.

 CE FORMAT N'EVOLUERA PLUS ET EST CONSIDERE COMME OBSOLETE.
 
"""
from reportlab.lib.colors import Color, blue
from reportlab.lib.units import cm, mm
from reportlab.platypus import Paragraph, Spacer, Table

from app.scodoc import sco_bulletins_generator
from app.scodoc import sco_bulletins_pdf
from app.scodoc import sco_formsemestre
from app.scodoc.sco_permissions import Permission
from app.scodoc import sco_pdf
from app.scodoc.sco_pdf import SU
from app.scodoc import sco_preferences
import app.scodoc.sco_utils as scu


# Important: Le nom de la classe ne doit pas changer (bien le choisir), car il sera stocké en base de données (dans les préférences)
class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
    description = "Ancien format ScoDoc"  # la description doit être courte: elle apparait dans le menu de paramètrage ScoDoc
    supported_formats = ["html", "pdf"]

    def bul_title_pdf(self):
        """Génère la partie "titre" du bulletin de notes.
        Renvoie une liste d'objets platypus
        """
        objects = sco_bulletins_pdf.process_field(
            self.preferences["bul_pdf_title"], self.infos, self.FieldStyle
        )
        objects.append(
            Spacer(1, 5 * mm)
        )  # impose un espace vertical entre le titre et la table qui suit
        return objects

    def bul_table(self, format="html"):
        """Table bulletin"""
        if format == "pdf":
            return self.bul_table_pdf()
        elif format == "html":
            return self.bul_table_html()
        else:
            raise ValueError("invalid bulletin format (%s)" % format)

    def bul_table_pdf(self):
        """Génère la table centrale du bulletin de notes
        Renvoie une liste d'objets PLATYPUS (eg instance de Table).
        """
        P, pdfTableStyle, colWidths = _bulletin_pdf_table_legacy(
            self.infos, version=self.version
        )
        return [self.buildTableObject(P, pdfTableStyle, colWidths)]

    def bul_table_html(self):
        """Génère la table centrale du bulletin de notes: chaine HTML"""
        I = self.infos
        formsemestre_id = self.infos["formsemestre_id"]

        bul_show_abs_modules = sco_preferences.get_preference(
            "bul_show_abs_modules", formsemestre_id
        )

        sem = sco_formsemestre.get_formsemestre(formsemestre_id)
        if sem["bul_bgcolor"]:
            bgcolor = sem["bul_bgcolor"]
        else:
            bgcolor = "background-color: rgb(255,255,240)"

        linktmpl = '<span onclick="toggle_vis_ue(this);" class="toggle_ue">%s</span>'
        minuslink = linktmpl % scu.icontag("minus_img", border="0", alt="-")
        pluslink = linktmpl % scu.icontag("plus_img", border="0", alt="+")

        H = ['<table class="notes_bulletin" style="background-color: %s;">' % bgcolor]

        if sco_preferences.get_preference("bul_show_minmax", formsemestre_id):
            minmax = (
                '<span class="bul_minmax" title="[min, max] promo">[%s, %s]</span>'
                % (I["moy_min"], I["moy_max"])
            )
            bargraph = ""
        else:
            minmax = ""
            bargraph = I["moy_gen_bargraph_html"]
        # 1ere ligne: titres
        H.append(
            '<tr><td class="note_bold">Moyenne</td><td class="note_bold cell_graph">%s%s%s%s</td>'
            % (I["moy_gen"], I["etud_etat_html"], minmax, bargraph)
        )
        H.append('<td class="note_bold">%s</td>' % I["rang_txt"])
        H.append('<td class="note_bold">Note/20</td><td class="note_bold">Coef</td>')
        if bul_show_abs_modules:
            H.append('<td class="note_bold">Abs (J. / N.J.)</td>')
        H.append("</tr>")

        def list_modules(ue_modules, rowstyle):
            for mod in ue_modules:
                if mod["mod_moy_txt"] == "NI":
                    continue  # saute les modules où on n'est pas inscrit
                H.append('<tr class="notes_bulletin_row_mod%s">' % rowstyle)
                if sco_preferences.get_preference(
                    "bul_show_minmax_mod", formsemestre_id
                ):
                    rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % (
                        mod["mod_rang_txt"],
                        scu.fmt_note(mod["stats"]["min"]),
                        scu.fmt_note(mod["stats"]["max"]),
                    )
                else:
                    rang_minmax = mod["mod_rang_txt"]  # vide si pas option rang
                H.append(
                    '<td>%s</td><td>%s</td><td>%s</td><td class="note">%s</td><td>%s</td>'
                    % (
                        mod["code_html"],
                        mod["name_html"],
                        rang_minmax,
                        mod["mod_moy_txt"],
                        mod["mod_coef_txt"],
                    )
                )
                if bul_show_abs_modules:
                    H.append("<td>%s</td>" % mod["mod_abs_txt"])
                H.append("</tr>")

                if self.version != "short":
                    # --- notes de chaque eval:
                    for e in mod["evaluations"]:
                        if e["visibulletin"] or self.version == "long":
                            H.append(
                                '<tr class="notes_bulletin_row_eval%s">' % rowstyle
                            )
                            H.append(
                                '<td>%s</td><td>%s</td><td class="bull_nom_eval">%s</td><td class="note">%s</td><td class="bull_coef_eval">%s</td></tr>'
                                % (
                                    "",
                                    "",
                                    e["name_html"],
                                    e["note_html"],
                                    e["coef_txt"],
                                )
                            )

        # Contenu table: UE après UE
        for ue in I["ues"]:
            ue_descr = ue["ue_descr_html"]
            coef_ue = ue["coef_ue_txt"]
            rowstyle = ""
            plusminus = minuslink  #
            if ue["ue_status"]["is_capitalized"]:
                if sco_preferences.get_preference(
                    "bul_show_ue_cap_details", formsemestre_id
                ):
                    plusminus = minuslink
                    hide = ""
                else:
                    plusminus = pluslink
                    hide = "sco_hide"
                H.append('<tr class="notes_bulletin_row_ue">')
                H.append(
                    '<td class="note_bold">%s%s</td><td class="note_bold">%s</td><td>%s</td><td>%s</td><td>%s</td>'
                    % (
                        plusminus,
                        ue["acronyme"],
                        ue["moy_ue_txt"],
                        ue_descr,
                        "",
                        coef_ue,
                    )
                )
                if bul_show_abs_modules:
                    H.append("<td></td>")
                H.append("</tr>")
                list_modules(ue["modules_capitalized"], " bul_row_ue_cap %s" % hide)

                coef_ue = ""
                ue_descr = "(en cours, non prise en compte)"
                rowstyle = (
                    " bul_row_ue_cur"  # style css pour indiquer UE non prise en compte
                )

            H.append('<tr class="notes_bulletin_row_ue">')
            if sco_preferences.get_preference("bul_show_minmax", formsemestre_id):
                moy_txt = (
                    '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>'
                    % (
                        scu.fmt_note(ue["cur_moy_ue_txt"]),
                        scu.fmt_note(ue["min"]),
                        scu.fmt_note(ue["max"]),
                    )
                )
            else:
                moy_txt = ue["cur_moy_ue_txt"]

            H.append(
                '<td class="note_bold">%s%s</td><td class="note_bold">%s</td><td>%s</td><td>%s</td><td>%s</td>'
                % (minuslink, ue["acronyme"], moy_txt, ue_descr, "", coef_ue)
            )
            if bul_show_abs_modules:
                H.append("<td></td>")
            H.append("</tr>")
            list_modules(ue["modules"], rowstyle)

        H.append("</table>")

        # ---------------
        return "\n".join(H)

    def bul_part_below(self, format="html"):
        """Génère les informations placées sous la table de notes
        (absences, appréciations, décisions de jury...)
        """
        if format == "pdf":
            return self.bul_part_below_pdf()
        elif format == "html":
            return self.bul_part_below_html()
        else:
            raise ValueError("invalid bulletin format (%s)" % format)

    def bul_part_below_pdf(self):
        """
        Renvoie une liste d'objets platypus
        """
        objects = []

        # ----- ABSENCES
        if self.preferences["bul_show_abs"]:
            nbabs = self.infos["nbabs"]
            nbabsjust = self.infos["nbabsjust"]
            objects.append(Spacer(1, 2 * mm))
            if nbabs:
                objects.append(
                    Paragraph(
                        SU(
                            "%d absences (1/2 journées), dont %d justifiées."
                            % (nbabs, nbabsjust)
                        ),
                        self.CellStyle,
                    )
                )
            else:
                objects.append(
                    Paragraph(SU("Pas d'absences signalées."), self.CellStyle)
                )

        # ----- APPRECIATIONS
        if self.infos.get("appreciations_list", False):
            objects.append(Spacer(1, 3 * mm))
            objects.append(
                Paragraph(
                    SU("Appréciation : " + "\n".join(self.infos["appreciations_txt"])),
                    self.CellStyle,
                )
            )

        # ----- DECISION JURY
        if self.preferences["bul_show_decision"]:
            objects += sco_bulletins_pdf.process_field(
                self.preferences["bul_pdf_caption"],
                self.infos,
                self.FieldStyle,
            )

        return objects

    def bul_part_below_html(self):
        """
        Renvoie chaine HTML
        """
        I = self.infos
        authuser = self.authuser
        H = []
        # --- Absences
        H.append(
            """<p>
        <a href="../Absences/CalAbs?etudid=%(etudid)s" class="bull_link">
        <b>Absences :</b> %(nbabs)s demi-journées, dont %(nbabsjust)s justifiées
        (pendant ce semestre).
        </a></p>
            """
            % I
        )
        # --- Decision Jury
        if I["situation"]:
            H.append("""<p class="bull_situation">%(situation)s</p>""" % I)
        # --- Appreciations
        # le dir. des etud peut ajouter des appreciations,
        # mais aussi le chef (perm. ScoEtudInscrit)
        can_edit_app = (authuser.id in self.infos["responsables"]) or (
            authuser.has_permission(Permission.ScoEtudInscrit)
        )
        H.append('<div class="bull_appreciations">')
        if I["appreciations_list"]:
            H.append("<p><b>Appréciations</b></p>")
        for app in I["appreciations_list"]:
            if can_edit_app:
                mlink = (
                    '<a class="stdlink" href="appreciation_add_form?id=%s">modifier</a> <a class="stdlink" href="appreciation_add_form?id=%s&suppress=1">supprimer</a>'
                    % (app["id"], app["id"])
                )
            else:
                mlink = ""
            H.append(
                '<p><span class="bull_appreciations_date">%s</span>%s<span class="bull_appreciations_link">%s</span></p>'
                % (app["date"], app["comment"], mlink)
            )
        if can_edit_app:
            H.append(
                '<p><a class="stdlink" href="appreciation_add_form?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s">Ajouter une appréciation</a></p>'
                % self.infos
            )
        H.append("</div>")
        # ---------------
        return "\n".join(H)

    def bul_signatures_pdf(self):
        """Génère les signatures placées en bas du bulletin
        Renvoie une liste d'objets platypus
        """
        show_left = self.preferences["bul_show_sig_left"]
        show_right = self.preferences["bul_show_sig_right"]
        if show_left or show_right:
            if show_left:
                L = [
                    [
                        sco_bulletins_pdf.process_field(
                            self.preferences["bul_pdf_sig_left"],
                            self.infos,
                            self.FieldStyle,
                        )
                    ]
                ]
            else:
                L = [[""]]
            if show_right:
                L[0].append(
                    sco_bulletins_pdf.process_field(
                        self.preferences["bul_pdf_sig_right"],
                        self.infos,
                        self.FieldStyle,
                    )
                )
            else:
                L[0].append("")
            t = Table(L)
            t._argW[0] = 10 * cm  # fixe largeur colonne gauche

            return [Spacer(1, 1.5 * cm), t]  # espace vertical avant signatures
        else:
            return []


# sco_bulletins_generator.register_bulletin_class(BulletinGeneratorLegacy)


class BulTableStyle(object):
    """Construction du style de tables reportlab platypus pour les bulletins "classiques" """

    LINEWIDTH = 0.5
    LINECOLOR = Color(0, 0, 0)
    UEBGCOLOR = Color(
        170 / 255.0, 187 / 255.0, 204 / 255.0
    )  # couleur fond lignes titres UE
    MODSEPCOLOR = Color(
        170 / 255.0, 170 / 255.0, 170 / 255.0
    )  # lignes séparant les modules

    def __init__(self):
        self.pdfTableStyle = [
            ("LINEBELOW", (0, 0), (-1, 0), self.LINEWIDTH, self.LINECOLOR)
        ]
        self.tabline = 0

    def get_style(self):
        "get resulting style (a list of platypus table commands)"
        # ajoute cadre extérieur bleu:
        self.pdfTableStyle.append(("BOX", (0, 0), (-1, -1), 0.4, blue))

        return self.pdfTableStyle

    def newline(self, ue_type=None):
        self.tabline += 1
        if ue_type == "cur":  # UE courante non prise en compte (car capitalisee)
            self.pdfTableStyle.append(
                (
                    "BACKGROUND",
                    (0, self.tabline),
                    (-1, self.tabline),
                    Color(210 / 255.0, 210 / 255.0, 210 / 255.0),
                )
            )

    def ueline(self):  # met la ligne courante du tableau pdf en style 'UE'
        self.newline()
        i = self.tabline
        self.pdfTableStyle.append(("BACKGROUND", (0, i), (-1, i), self.UEBGCOLOR))

    def modline(
        self, ue_type=None
    ):  # met la ligne courante du tableau pdf en style 'Module'
        self.newline(ue_type=ue_type)
        i = self.tabline
        self.pdfTableStyle.append(("LINEABOVE", (0, i), (-1, i), 1, self.MODSEPCOLOR))


def _bulletin_pdf_table_legacy(I, version="long"):
    """Génère la table centrale du bulletin de notes
    Renvoie un triplet:
    - table (liste de listes de chaines de caracteres)
    - style (commandes table Platypus)
    - largeurs de colonnes
    """
    S = BulTableStyle()
    P = []  # elems pour gen. pdf
    formsemestre_id = I["formsemestre_id"]
    bul_show_abs_modules = sco_preferences.get_preference(
        "bul_show_abs_modules", formsemestre_id
    )

    if sco_preferences.get_preference("bul_show_minmax", formsemestre_id):
        minmax = ' <font size="8">[%s, %s]</font>' % (I["moy_min"], I["moy_max"])
    else:
        minmax = ""

    t = [
        "Moyenne",
        "%s%s%s" % (I["moy_gen"], I["etud_etat_html"], minmax),
        I["rang_txt"],
        "Note/20",
        "Coef",
    ]
    if bul_show_abs_modules:
        t.append("Abs (J. / N.J.)")
    P.append(sco_pdf.bold_paras(t))

    def list_modules(ue_modules, ue_type=None):
        "ajoute les lignes decrivant les modules d'une UE, avec eventuellement les évaluations de chacun"
        for mod in ue_modules:
            if mod["mod_moy_txt"] == "NI":
                continue  # saute les modules où on n'est pas inscrit
            S.modline(ue_type=ue_type)
            if sco_preferences.get_preference("bul_show_minmax_mod", formsemestre_id):
                rang_minmax = '%s <font size="8">[%s, %s]</font>' % (
                    mod["mod_rang_txt"],
                    scu.fmt_note(mod["stats"]["min"]),
                    scu.fmt_note(mod["stats"]["max"]),
                )
            else:
                rang_minmax = mod["mod_rang_txt"]  # vide si pas option rang
            t = [
                mod["code"] or "",
                mod["name"] or "",
                rang_minmax,
                mod["mod_moy_txt"],
                mod["mod_coef_txt"],
            ]
            if bul_show_abs_modules:
                t.append(mod["mod_abs_txt"])
            P.append(t)
            if version != "short":
                # --- notes de chaque eval:
                for e in mod["evaluations"]:
                    if e["visibulletin"] or version == "long":
                        S.newline(ue_type=ue_type)
                        t = ["", "", e["name"], e["note_txt"], e["coef_txt"]]
                        if bul_show_abs_modules:
                            t.append("")
                        P.append(t)

    for ue in I["ues"]:
        ue_descr = ue["ue_descr_txt"]
        coef_ue = ue["coef_ue_txt"]
        ue_type = None
        if ue["ue_status"]["is_capitalized"]:
            t = [ue["acronyme"], ue["moy_ue_txt"], ue_descr, "", coef_ue]
            if bul_show_abs_modules:
                t.append("")
            P.append(sco_pdf.bold_paras(t))
            coef_ue = ""
            ue_descr = "(en cours, non prise en compte)"
            S.ueline()
            if sco_preferences.get_preference(
                "bul_show_ue_cap_details", formsemestre_id
            ):
                list_modules(ue["modules_capitalized"])
            ue_type = "cur"

        if sco_preferences.get_preference("bul_show_minmax", formsemestre_id):
            moy_txt = '%s <font size="8">[%s, %s]</font>' % (
                ue["cur_moy_ue_txt"],
                ue["min"],
                ue["max"],
            )
        else:
            moy_txt = ue["cur_moy_ue_txt"]
        t = [ue["acronyme"], moy_txt, ue_descr, "", coef_ue]
        if bul_show_abs_modules:
            t.append("")
        P.append(sco_pdf.bold_paras(t))
        S.ueline()
        list_modules(ue["modules"], ue_type=ue_type)

    # Largeur colonnes:
    colWidths = [None, 5 * cm, 6 * cm, 2 * cm, 1.2 * cm]
    if len(P[0]) > 5:
        colWidths.append(1.5 * cm)  # absences/modules

    return P, S.get_style(), colWidths