import "jest-extended";
import { Devoir } from "../../src/classes/devoir";
import { Cours } from "../../src/classes/cours";
import { Etudiant } from "../../src/classes/etudiant";
import { HoraireCours } from '../../src/classes/horaireCours';
import { DevoirControleur } from "../../src/controleurs/devoirControleur";

// configuration devoir
const nom = "DEVOIR TEST";
const reponse = true;
const enseignant = "ENSEIGNANT TEST";
const note_max = 10;
const description = "DESCRIPTION TEST";
const date_debut = new Date("2020-01-01");
const date_fin = new Date("2020-01-02");
const actif = true;
const devoir_id = "D01";

// configuration cours
const id = "ABC123";
const group_id = "S2023-ABC123-01";
const day = "lundi";
const hours = "8h-10h";
const activity = "C";
const mode = "P";
const local = "A-2500"
const prealable = "XYZ987";
const titre = "Cours sur ABC";
const teacher_id = "michel.vaillancourt@etsmtl.ca";
const etudiants_ids = [
  new Etudiant("ABC123", "Michel", "Vaillancourt")
];

const horaire_cours = [new HoraireCours(
  group_id,
  day,
  hours,
  activity,
  mode,
  local,
  teacher_id,
  )];

  let devoir: Devoir;
  let devoirControleur: DevoirControleur;
  let cours : Cours;

describe('Ajouter Devoir test', () => {
    beforeEach(async() =>  {
        devoirControleur = new DevoirControleur();
        cours = new Cours(id, group_id, prealable, titre, etudiants_ids, horaire_cours);
        devoir = new Devoir(nom, description, date_debut, date_fin, note_max, actif);
        devoirControleur.ajouterDevoir(cours, devoir);
    });

    it('devrait valider l\'ajout du devoir', async () => {
        let nouveauDevoir = new Devoir("nouveauDevoir", description, date_debut, date_fin, note_max, actif);
        devoirControleur.ajouterDevoir(cours, nouveauDevoir);
        const result = devoirControleur.recupererDevoir(cours, nouveauDevoir.id);
        expect(result).toBe(nouveauDevoir);
        const resultListeDevoir = devoirControleur.recupererListeDevoir(cours);
        expect(resultListeDevoir.length).toBe(2);
    });

    it('devrait valider que le devoir créé est associé au cours', async () => {
        let devoirAssocie = cours.liste_travaux.find(t => t.id === devoir.id);
        expect(devoirAssocie).toBe(devoir);
    });

    it('devrait valider que le devoir créé n\'est pas associe à un autre cours', async () => {
        let cours2 = new Cours("ABC456", "S2023-ABC123-01", prealable, titre, etudiants_ids, horaire_cours);
        let devoirAssocie = cours2.liste_travaux.find(t => t.id === devoir.id);
        expect(devoirAssocie).toBe(undefined);
    });

    it('devrait valider que la date de début est avant la date de fin lors de l\'ajout d\'un devoir (SUCCES)', async () => {
        let nouveauDevoir = new Devoir("nouveauDevoir", description, date_debut, date_fin, note_max, actif);
        devoirControleur.ajouterDevoir(cours, nouveauDevoir);
        const result = devoirControleur.recupererDevoir(cours, nouveauDevoir.id);
        expect(result).toBe(nouveauDevoir);        
        expect(nouveauDevoir.dateFin > nouveauDevoir.dateDebut).toBe(true);
    });

    it('devrait valider que la date de début est avant la date de fin lors de l\'ajout d\'un devoir (ERROR)', async () => {
        let nouveauDevoir = new Devoir("nouveauDevoir", description, date_fin, date_debut, note_max, actif);
        devoirControleur.ajouterDevoir(cours, nouveauDevoir);
        const result = devoirControleur.recupererDevoir(cours, nouveauDevoir.id);
        expect(result).toBe(nouveauDevoir);        
        expect(nouveauDevoir.dateFin > nouveauDevoir.dateDebut).toBe(false);
    });


    it('devrait valider qu\'un deuxième devoir peut être créer et associé au même cours', async () => {
        let nouveauDevoir = new Devoir("nouveauDevoir", description, date_fin, date_debut, note_max, actif);
        devoirControleur.ajouterDevoir(cours, nouveauDevoir);
        const result = devoirControleur.recupererListeDevoir(cours);
        expect(result.length).toBe(2);
        expect(result[0]).toBe(devoir);
        expect(result[1]).toBe(nouveauDevoir);
    });

    it('devrait valider qu\'il n\'est pas possible de nommer deux devoir avec le même nom', async () => {
        const resultAvant = devoirControleur.recupererListeDevoir(cours);
        expect(resultAvant.length).toBe(1);
        let nouveauDevoir = new Devoir(nom, "secondeDescrition", date_debut, date_fin, note_max, actif);
        const result = devoirControleur.ajouterDevoir(cours, nouveauDevoir);
        expect(result).toBe(false);
        const resultApres= devoirControleur.recupererListeDevoir(cours);
        expect(resultApres.length).toBe(1);
        expect(resultApres[0]).toBe(devoir);
    });

});

describe ('Recuperation Devoir test', () => {
    beforeEach(async() =>  {
        devoirControleur = new DevoirControleur();
        cours = new Cours(id, group_id, prealable, titre, etudiants_ids, horaire_cours);
        devoir = new Devoir(nom, description, date_debut, date_fin, note_max, actif);
        let nouveauDevoir = new Devoir("nouveauDevoir", description, date_fin, date_debut, note_max, actif);
        devoirControleur.ajouterDevoir(cours, devoir);
        devoirControleur.ajouterDevoir(cours, nouveauDevoir);
    });

    it('devrait valider la recuperation d\'un devoir', async () => {
        const result = devoirControleur.recupererDevoir(cours, devoir.id);
        let devoirDuCours = cours.liste_travaux.find(t => t.id === devoir.id);
        expect(result).toBe(devoirDuCours);
    });

    it('devrait valider la recuperation de tous les devoirs d\'un cours', async () => {
        const result = devoirControleur.recupererListeDevoir(cours);
        expect(result[0]).toBe(devoir);
        expect(result.length).toBe(2);
    });

    it('devrait valider la recuperation de tous les devoirs', async () => {
        const result = devoirControleur.recupererTousDevoir([cours]);
        result.forEach((value) => {
            expect(value).toBe(cours);
        });
        expect(result.size).toBe(2);
    });
    
});

describe ('Modifier Devoir test', () => {
    beforeEach(async() =>  {
        devoirControleur = new DevoirControleur();
        cours = new Cours(id, group_id, prealable, titre, etudiants_ids, horaire_cours);
        devoir = new Devoir(nom, description, date_debut, date_fin, note_max, actif);
        devoirControleur.ajouterDevoir(cours, devoir);
    });

    it('devrait valider la modification d\'un devoir avec plusieurs devoirs', async () => {
        let nouveauDateDebut = new Date("2020-01-03");
        let nouveauDateFin = new Date("2020-01-04");
        let nouveauNom = "NOUVEAU DEVOIR TEST";
        let nouveauDescription = "NOUVELLE DESCRIPTION TEST";
        let nouveauNoteMax = 20;
        let nouveauActif = false;
        let secondDevoir = new Devoir("SECOND DEVOIR TEST", nouveauDescription, nouveauDateDebut, nouveauDateFin, nouveauNoteMax, nouveauActif);
        devoirControleur.ajouterDevoir(cours, secondDevoir);
        let nouveauDevoir = new Devoir(nouveauNom, nouveauDescription, nouveauDateDebut, nouveauDateFin, nouveauNoteMax, nouveauActif);
        const result = devoirControleur.modifierDevoir(cours, nouveauDevoir, devoir_id);
        expect(result).toBe(nouveauDevoir);
        const resultListeDevoir = devoirControleur.recupererListeDevoir(cours);
        expect(resultListeDevoir.length).toBe(2);
        expect(resultListeDevoir[1]).toBe(secondDevoir);
    });

    it('devrait valider qu\'un ne peut modifier le devoir pour mettre un nom déjà existant', async () => {
        let devoir2 = new Devoir("devoir2", description, date_fin, date_debut, note_max, actif);
        devoirControleur.ajouterDevoir(cours, devoir2);

        let devoirRemplacent = new Devoir(nom, description, date_fin, date_debut, note_max, actif);

        const result = devoirControleur.modifierDevoir(cours, devoirRemplacent, devoir2.id);
        expect(result).toBe(undefined);
    });

});

describe ('Retrait Devoir test', () => {
    beforeEach(async() =>  {
        devoirControleur = new DevoirControleur();
        cours = new Cours(id, group_id, prealable, titre, etudiants_ids, horaire_cours);
        devoir = new Devoir(nom, description, date_debut, date_fin, note_max, actif);
        let devoir2 = new Devoir("devoir2", description, date_fin, date_debut, note_max, actif);
        devoirControleur.ajouterDevoir(cours, devoir);
        devoirControleur.ajouterDevoir(cours, devoir2);
    });

    it('devrait valider le retrait d\'un devoir', async () => {
        const resultAvant = devoirControleur.recupererListeDevoir(cours);
        expect(resultAvant.length).toBe(2);
        let devoirAssocie = cours.liste_travaux.find(t => t.id === devoir.id);
        expect(devoirAssocie).toBe(devoir);
        devoirControleur.retirerDevoir(cours, devoir.id);
        const resultApres = devoirControleur.recupererListeDevoir(cours);
        expect(resultApres.length).toBe(1);
        devoirAssocie = cours.liste_travaux.find(t => t.id === devoir.id);
        expect(devoirAssocie).toBe(undefined);
    });
    
});