package API;

import java.util.*;

/**
 * Usine abstraite gérant l'ensemble des groupes.
 */

public interface AbstractGroupeFactory {

    /**
     * permet de récupérer le Groupe qui contient les étudiants de toute la promotion
     *
     * @return la promo.
     */
    public Groupe getPromotion();


    /**
     * Test si le groupe g est connu de l'usine (connu maintenant).
     * Si la réponse est true, les méthodes avec ce groupe en paramètre devraient bien fonctionner.
     * Si la réponse est false, le comportement n'est pas garanti.
     */
    public Boolean knows(Groupe g);


    /**
     * permet de supprimer un groupe connu de l'usine abstraite qui ne contient pas de groupes.
     * Pour détruire un groupe connu qui en contient d'autres il faut le faire récursivement.
     *
     * @throws java.lang.NullPointerException     si un argument est null
     * @throws java.lang.IllegalStateException    si le groupe contient des groupes
     * @throws java.lang.IllegalArgumentException si le groupe n'est pas connu de l'usine abstraite ou bien si le groupe est celui de toute la promotion (renvoyé par getPromotion)
     */
    public void deleteGroupe(Groupe g);

    /**
     * permet d'ajouter un groupe vide de type FREE comme sous-groupe d'un groupe donné.
     *
     * @param pere    le groupe père du groupe à créer
     * @param name    le nom du groupe à créer
     * @param min,max bornes indicatives sur la taille du groupe à créer
     * @throws java.lang.NullPointerException     si un argument est null
     * @throws java.lang.IllegalArgumentException si le groupe pere est de type PARTITION
     *                                            ou si il n'y a pas 0 < min <= max
     */
    public void createGroupe(Groupe pere, String name, int min, int max);

    /**
     * permet de créer une partition automatiquement sous un groupe donné.
     *
     * @param pere le groupe père du groupe à partitionner
     * @param name le nom des groupe à créer (on ajoutera à la suite un numéro ou une lettre pour distinguer chaque groupe)
     * @param n    le nombre de partitions
     * @throws java.lang.NullPointerException     si un argument est null
     * @throws java.lang.IllegalArgumentException si le groupe pere est de type PARTITION
     *                                            ou n négatif ou nul
     *                                            <p>
     *                                            NB. doit créer une "copie" de pere
     *                                            sous pere de type Partition et ajouter sous ce groupe, n groupes de type "FREE".
     *                                            les valeurs min et max de ces n groupes sont
     *                                            min = 0 et
     *                                            max = partie entière de N/n plus 1, où N est le nombre max du groupe pere.
     */
    public void createPartition(Groupe pere, String name, int n);

    /**
     * permet d'ajouter un étudiant à un groupe.
     *
     * @param g le groupe dans lequel il faut ajouter l'étudiant
     * @param e l'étudiant à ajouter
     * @throws java.lang.NullPointerException     si un argument est null
     * @throws java.lang.IllegalArgumentException la factory ne connaît pas g
     * @throws java.lang.IllegalStateException    le père de g ne contient pas e
     */
    public void addToGroupe(Groupe g, Etudiant e);

    /**
     * permet d'enlever un étudiant d'un groupe.
     *
     * @param g le groupe dans lequel il faut enlever l'étudiant
     * @param e l'étudiant à enlever
     * @throws java.lang.NullPointerException     si un argument est null
     * @throws java.lang.IllegalStateException    g ne contient pas e
     * @throws java.lang.IllegalArgumentException la factory ne connaît pas g
     */
    public void dropFromGroupe(Groupe g, Etudiant e);

    /**
     * permet de retrouver un étudiant à partir d'un String.
     * <p>
     * NB. dans une version simple il doit s'agir du nom exact.
     * dans une version un peu plus complexe, il s'agit des premières lettres du nom
     * dans une version avancée, on peut autoriser une expression régulière plus ou moins complexe qui est générée si la première recherche n'a pas renvoyé de candidat.
     *
     * @param String nomEtu le nom approximmatif de l'étudiant
     * @return Set<Etudiant> l'ensemble des étudiants connus de la factory ayant un nom "proche" de ce string au sens de la remarque ci-dessus.
     * @throws java.lang.NullPointerException si le String est null.
     */
    public Set<Etudiant> getEtudiants(String nomEtu);

    /**
     * permet de retrouver les groupes d'un étudiant.
     *
     * @param Etu un étudiant
     * @return Etudiant l'étudiant connu de la factory ayant cet identifiant
     * @throws java.lang.NullPointerException si le String est null.
     */
    public Set<Groupe> getGroupesOfEtudiant(Etudiant etu);


}
