import { ConduiteDistrib, ConduiteDistribParams } from "../../src/cond_distri";
import { ParamValueMode, SectionParametree, Session } from "../../src/index";
import { CourbeRemous, CourbeRemousParams, MethodeResolution } from "../../src/remous";
import { cSnCirc, ParamsSectionCirc } from "../../src/section/section_circulaire";
import { cSnTrapez, ParamsSectionTrapez } from "../../src/section/section_trapez";
import { Cloisons } from "../../src/structure/cloisons";
import { CloisonsParams } from "../../src/structure/cloisons_params";
import { Dever, DeverParams } from "../../src/structure/dever";
import { CreateStructure } from "../../src/structure/factory_structure";
import { LoiDebit } from "../../src/structure/structure_props";
import {
    RectangularStructureParams,
    StructureWeirSubmergedLarinier
} from "../../src/structure/structure_weir_submerged_larinier";

/**
 * IMPORTANT !
 * Décommenter temporairement la ligne suivante (import { } from "./mock_jasmine")
 * Pour exécuter ce code dans le débugger.
 * Faire de même avec le fichier test_func.ts
 */
// import { describe, expect, it, xdescribe, xit } from "../mock_jasmine";

function createEnv() {
    // create complex session
    const dever: Dever = new Dever(
        new DeverParams(
            0,     // rQ Débit total (m3/s)
            102,   // rZ1 Cote de l'eau amont (m)
            2,     // rBR Largeur du cours d'eau amont (m)
            100    // rZR Cote du lit du cours d'eau amont (m)
        ),
        false // debug
    );
    dever.addChild(CreateStructure(LoiDebit.TriangularTruncWeirFree, dever, false));

    const cloisons: Cloisons = new Cloisons(
        new CloisonsParams(
            0,      // Débit total (m3/s)
            102,    // Cote de l'eau amont (m)
            10,     // Longueur des bassins (m)
            1,      // Largeur des bassins (m)
            1,      // Profondeur moyenne (m)
            0.5     // Hauteur de chute (m)
        ),
        false       // debug
    );
    const fente: StructureWeirSubmergedLarinier = new StructureWeirSubmergedLarinier(
        new RectangularStructureParams(
            0,
            101,
            102,
            101.5,
            0.2,
            0.65
        )
    );
    cloisons.addChild(fente);

    const prmsCD = new ConduiteDistribParams(undefined, // débit Q
        1.2, // diamètre D
        0.6, // perte de charge J
        100, // Longueur de la conduite Lg
        1e-6, // Viscosité dynamique Nu
    );
    const conduite = new ConduiteDistrib(prmsCD);

    const prmsST = new ParamsSectionTrapez(2.5, // largeur de fond
        0.56, // fruit
        undefined, // tirant d'eau
        40, //  Ks=Strickler
        2,  //  Q=Débit
        0.001, //  If=pente du fond
        1, // YB= hauteur de berge
    );
    const sect = new cSnTrapez(prmsST);
    const prem = new CourbeRemousParams(0.15, // Yamont = tirant amont
        0.803, // Yaval = tirant aval
        5,  // Long= Longueur du bief
        5,  // Dx=Pas d'espace
    );
    const rem = new CourbeRemous(sect, prem, MethodeResolution.Trapezes);

    const paramSection = new ParamsSectionCirc(2, // diamètre
        0.8, // tirant d'eau
        40, //  Ks=Strickler
        10,  //  Q=Débit
        0.001, //  If=pente du fond
        1, // YB= hauteur de berge
    );
    const section = new cSnCirc(paramSection);
    const sp = new SectionParametree(section);

    Session.getInstance().clear();
    Session.getInstance().registerNub(dever);
    Session.getInstance().registerNub(cloisons);
    Session.getInstance().registerNub(conduite);
    Session.getInstance().registerNub(rem);
    Session.getInstance().registerNub(sp);
}

describe("serialising / deserialising session - ", () => {

    it ("serialized file should contain 5 Nubs", () => {
        createEnv();
        const session = Session.getInstance().serialise();
        const js = JSON.parse(session);
        expect(Object.keys(js)).toContain("session");
        expect(js.session.length).toBe(5);
    });

    it ("reloading serialized file should give 5 Nubs", () => {
        createEnv();
        const session = Session.getInstance().serialise();

        Session.getInstance().clear();
        expect(Session.getInstance().getNumberOfNubs()).toBe(0);

        Session.getInstance().unserialise(session);
        expect(Session.getInstance().getNumberOfNubs()).toBe(5);
    });

    it("when saving a SectionParametree, the edited values should be present in the file", () => {
        // d
        const paramSection = new ParamsSectionCirc(
            2, // diamètre
            0.8, // tirant d'eau
            40, //  Ks=Strickler
            10,  //  Q=Débit
            0.001, //  If=pente du fond
            1, // YB= hauteur de berge
        );
        const section = new cSnCirc(paramSection);
        const sp = new SectionParametree(section);
        sp.section.prms.Ks.v = 42;

        const serialised = sp.serialise();
        expect(serialised).toContain('{"symbol":"Ks","mode":"SINGLE","value":42}');
    });

    it ("loaded serialized RegimeUniforme should be calculable", () => {
        Session.getInstance().clear();
        // tslint:disable-next-line:max-line-length
        const session = `{"session":[{"uid":"YTEwZG","props":{"calcType":3,"nodeType":2},"meta":{"title":"R. uniforme"},"children":[{"uid":"NDcxN3","props":{"calcType":14,"nodeType":2},"children":[],"parameters":[{"symbol":"Pr","mode":"SINGLE","value":0.0001},{"symbol":"Ks","mode":"SINGLE","value":40},{"symbol":"Q","mode":"CALCUL"},{"symbol":"If","mode":"SINGLE","value":0.001},{"symbol":"YB","mode":"SINGLE","value":1},{"symbol":"Y","mode":"SINGLE","value":0.89},{"symbol":"LargeurBerge","mode":"SINGLE","value":2.5}]}],"parameters":[{"symbol":"Pr","mode":"SINGLE","value":0.0001}]}]}`;
        Session.getInstance().unserialise(session);

        expect(Session.getInstance().getNumberOfNubs()).toBe(1);

        const RU = Session.getInstance().findNubByUid("YTEwZG");
        expect(RU).toBeDefined();

        const calculatedParam = RU.calculatedParam;
        expect(calculatedParam.symbol).toBe("Q");

        let nbCalc = 0;
        for (const p of RU.parameterIterator) {
            if (p.valueMode === ParamValueMode.CALCUL) {
                nbCalc++;
            }
        }
        expect(nbCalc).toBe(1);

        RU.CalcSerie();
        expect(RU.result).toBeDefined();
    });

    it ("loaded serialized Ouvrages should be calculable", () => {
        Session.getInstance().clear();
        // tslint:disable-next-line:max-line-length
        const session = `{"session":[{"uid":"NGVzdz","props":{"calcType":8,"nodeType":0},"meta":{"title":"Ouvrages"},"children":[{"uid":"Z2F4dz","props":{"calcType":7,"nodeType":5,"structureType":1,"loiDebit":1},"children":[],"parameters":[{"symbol":"ZDV","mode":"SINGLE","value":100},{"symbol":"W","mode":"SINGLE","value":0.5},{"symbol":"L","mode":"SINGLE","value":2},{"symbol":"Cd","mode":"SINGLE","value":0.6}]},{"uid":"ZDR4cX","props":{"calcType":7,"nodeType":5,"structureType":1,"loiDebit":1},"children":[],"parameters":[{"symbol":"ZDV","mode":"SINGLE","value":100},{"symbol":"W","mode":"SINGLE","value":0.5},{"symbol":"L","mode":"CALCUL"},{"symbol":"Cd","mode":"SINGLE","value":0.6}]}],"parameters":[{"symbol":"Pr","mode":"SINGLE","value":0.0001},{"symbol":"Q","mode":"SINGLE","value":3.5},{"symbol":"Z1","mode":"SINGLE","value":102},{"symbol":"Z2","mode":"SINGLE","value":101.5}]}]}`;
        Session.getInstance().unserialise(session);

        expect(Session.getInstance().getNumberOfNubs()).toBe(1);

        const OUV = Session.getInstance().findNubByUid("NGVzdz");
        expect(OUV).toBeDefined();

        const calculatedParam = OUV.calculatedParam;
        expect(calculatedParam.symbol).toBe("L");

        let nbCalc = 0;
        for (const p of OUV.parameterIterator) {
            if (p.valueMode === ParamValueMode.CALCUL) {
                nbCalc++;
            }
        }
        expect(nbCalc).toBe(1);

        OUV.CalcSerie();
        expect(OUV.result).toBeDefined();
        expect(OUV.result.vCalc).toBeCloseTo(1.031);
    });

});