from app.models import FormSemestre
import app.pe.rcss.pe_rcs as pe_rcs


class Trajectoire(pe_rcs.RCS):
    """Regroupement Cohérent de Semestres ciblant un type d'aggrégat (par ex.
    'S2', '3S', '1A') et un semestre final, et dont les données regroupées
    sont des **FormSemestres** suivis par les étudiants.

    Une *Trajectoire* traduit la succession de semestres
    qu'ont pu suivre des étudiants pour aller d'un semestre S1 jusqu'au semestre final
    de l'aggrégat.

    Une *Trajectoire* peut être :

    * un RCS de semestre de type "Sx" (cf. classe "SemX"), qui stocke les
      formsemestres de rang x qu'ont suivi l'étudiant pour valider le Sx
      (en général 1 formsemestre pour les non-redoublants et 2 pour les redoublants)

    * un RCS de type iS ou iA (par ex, 3A=S1+S2+S3), qui identifie
      les formsemestres que des étudiants ont suivis pour les amener jusqu'au semestre
      terminal du RCS. Par ex: si le RCS est un 3S:

        * des S1+S2+S1+S2+S3 si redoublement de la 1ère année
        * des S1+S2+(année de césure)+S3 si césure, ...

    Args:
        nom: Un nom du RCS (par ex: '5S')
        semestre_final: Le formsemestre final du RCS
    """

    def __init__(self, nom: str, semestre_final: FormSemestre):
        pe_rcs.RCS.__init__(self, nom, semestre_final)

        self.semestres_aggreges: dict[int:FormSemestre] = {}
        """Formsemestres regroupés dans le RCS"""

    def add_semestres(self, semestres: dict[int:FormSemestre]):
        """Ajout de semestres aux semestres à regrouper

        Args:
            semestres: Dictionnaire ``{fid: Formsemestre)``
        """
        for sem in semestres.values():
            assert isinstance(
                sem, FormSemestre
            ), "Les données aggrégées d'une Trajectoire doivent être des FormSemestres"
        self.semestres_aggreges = self.semestres_aggreges | semestres

    def get_repr(self, verbose=True) -> str:
        """Représentation textuelle d'un RCS
        basé sur ses semestres aggrégés"""
        title = f"""{self.__class__.__name__} {pe_rcs.RCS.__str__(self)}"""
        if verbose:
            noms = []
            for fid in self.semestres_aggreges:
                semestre = self.semestres_aggreges[fid]
                noms.append(f"S{semestre.semestre_id}#{fid}")
            noms = sorted(noms)
            if noms:
                title += " <" + "+".join(noms) + ">"
            else:
                title += " <vide>"
        return title


class SemX(Trajectoire):
    """Trajectoire (regroupement cohérent de (form)semestres
    dans laquelle tous les semestres regroupés sont de même rang `x`.

    Les SemX stocke les
    formsemestres de rang x qu'ont suivi l'étudiant pour valider le Sx
    (en général 1 formsemestre pour les non-redoublants et 2 pour les redoublants).

    Ils servent à calculer les SemXTag (moyennes par tag des RCS de type `Sx`).
    """

    def __init__(self, trajectoire: Trajectoire):
        Trajectoire.__init__(self, trajectoire.nom, trajectoire.formsemestre_final)

        semestres_aggreges = trajectoire.semestres_aggreges
        for sem in semestres_aggreges.values():
            assert (
                sem.semestre_id == trajectoire.rang_final
            ), "Tous les semestres aggrégés d'un SemX doivent être de même rang"

        self.semestres_aggreges = trajectoire.semestres_aggreges