export var poleTopologii = [];
export var poleSpoju = [];
export var poleStanic = [];
export var poleSouboru = [];


export class Stanice {
    constructor(nazev, lat, long, poznamka, poradi, nazevTopologie) {
        this.nazev = nazev;
        this.lat = lat;
        this.long = long;
        this.poznamka = poznamka;
        this.poradi = poradi;
        this.nazevTopologie = nazevTopologie;
        this.staryNazev = nazev;
        this.odstranit = false;
        this.radek;

        // Proměnné pro mapu
        this.visible = false;
        this.marker;

        if (poznamka == undefined) this.poznamka = null;
        if (poradi == undefined) this.poradi = null;

        poleStanic.push(this);

    }

    static vytvoritStaniceSQL(mnozinaStanic) {
        var vytvoreneStanice = [];
        for (let i = 0; i < mnozinaStanic.length; i++) {
            let nazev = mnozinaStanic[i].Nazev;
            let lat = mnozinaStanic[i].Latitude;
            let long = mnozinaStanic[i].Longitude;
            let poznamka = mnozinaStanic[i].Poznamka;
            let id = mnozinaStanic[i].Poradi;
            let nazevTopologie = mnozinaStanic[i].Topologie;
            vytvoreneStanice.push(new Stanice(nazev, lat, long, poznamka, id, nazevTopologie));
        }
        return vytvoreneStanice;
    }
}



export class Topologie {


    constructor(nazev, typ, poznamka) {
        this.nazev = nazev;
        this.typ = typ;
        this.poznamka = poznamka;
        if (poznamka == undefined) this.poznamka = null;

        this.staryNazev = nazev;
        this.odstranit = false;

        this.tabulkaStanic;
        this.tabulkaSpoju;

        this.radek;

        // Proměnné pro mapu
        this.visible = false;

        this.poleSpoju = [];
        this.poleStanic = [];
        poleTopologii.push(this);
    }

    static vytvoritTopologieSQL(mnozinaObjektu) {
        var vytvoreneObjekty = [];
        for (let i = 0; i < mnozinaObjektu.length; i++) {
            let nazev = mnozinaObjektu[i].Nazev;
            let typ = mnozinaObjektu[i].Typ;
            let poznamka = mnozinaObjektu[i].Poznamka;
            vytvoreneObjekty.push(new Topologie(nazev, typ, poznamka));
        }
        return vytvoreneObjekty;
    }


}


export class Spoj {

    static poleSpoju = [];

    constructor(A, B, typ, topologie) {
        // Obecne parametry
        this.A = A;
        this.B = B;
        this.nazev = A.nazev + " -> " + B.nazev;
        this.topologie = topologie;
        this.typ = typ;
        this.download;
        this.upload;
        this.poznamka;
        this.vzdalenost;
        this.oznaceni;
        this.staryNazev = this.nazev;
        this.odstranit = false;

        // Proměnné pro mapu
        this.visible = false;
        this.polyline;

        //BPL
        this.koeficient;
        this.pocetSpojek;
        this.typSpojek;
        this.rokInstalaceSpojek;
        this.typKabelu;
        this.rokInstalaceKabelu;
        this.rx;
        this.tx;
        this.delkaUsekuKabelu;
        this.prurezKabelu;
        this.materialSpojek;
        this.zatez;
        this.zemneni;

        // MW
        this.rxMHz;
        this.txMHz;
        this.bandwithMHz;
        this.modulace;

        // PŘIDÁNÍ PARAMETRŮ PRO SPECIFICKOU TECHNOLOGII


        if (this.typ != "koeficient") poleSpoju.push(this);

    }

    rename() {
        this.nazev = this.A.nazev + " -> " + this.B.nazev;
    }

    print() {
        let vzdalenost = this.vzdalenost;
        let download = this.download;
        let upload = this.upload;

        if (vzdalenost == 0) vzdalenost = "<b style=\"color:red\">-</b>";
        else vzdalenost = vzdalenost + " km";

        if (download == 0) download = "<b style=\"color:red\">  - </b>";
        if (upload == 0) upload = "<b style=\"color:red\"> - </b>";

        let text = "<br><b>Technologie: </b>" + this.typ +
            "<br><b>Rychlost Down/Up: </b>" + download + "<b>/</b>" + upload + " Mbps" +
            "<br><b>Vzdálenost: </b>" + vzdalenost;


        switch (this.typ) {
            case "BPL":
                // Numerické parametry - nastavení prázdných hodnot v případě hodnoty, která odpovídá "neznámému parametru"
                let prurezKabelu = this.prurezKabelu;
                let pocetSpojek = this.pocetSpojek;
                let zatez = this.zatez;
                let rx = this.rx;
                let tx = this.tx;


                if (prurezKabelu == 0) prurezKabelu = "neznámý";
                else prurezKabelu = prurezKabelu + " mm<sup>2</sup>";

                let pocetTypSpojek;
                if (pocetSpojek == -1) {
                    pocetSpojek = "<i style=\"color:red\">neznámý</i>";
                    if (this.typSpojek != "") pocetTypSpojek = "<b>Počet:</b> " + pocetSpojek + ", <b>Typ:</b> " + this.typSpojek;
                    else pocetTypSpojek = "<b>Počet:</b> " + pocetSpojek + ", <b>Typ:</b> <i style=\"color:red\">neznámý</i>";
                }

                if (pocetSpojek == 0) {
                    pocetTypSpojek = pocetSpojek;
                }

                if (pocetSpojek > 0) {
                    if (this.typSpojek != "") pocetTypSpojek = "<b>Počet:</b> " + pocetSpojek + ", <b>Typ:</b> " + this.typSpojek;
                    else pocetTypSpojek = "<b>Počet:</b> " + pocetSpojek + ", <b>Typ:</b> <i style=\"color:red\">neznámý</i>";
                }

                if (zatez == -1) zatez = "<b style=\"color:red\"> - </b>";
                if (rx == 0) rx = "<b style=\"color:red\"> - </b>";
                if (tx == 0) tx = "<b style=\"color:red\"> - </b>";


                text = text + "<br><b style=\"color:#4863A0\">Délka kabelových úseků: </b>" + this.delkaUsekuKabelu +
                    "<br><b style=\"color:#4863A0\">Rok instalace kabelových úseků: </b>" + this.rokInstalaceKabelu +
                    "<br><b style=\"color:#4863A0\">Typ kabelu: </b>" + this.typKabelu +
                    "<br><b style=\"color:#4863A0\">Průřez kabelu: </b>" + prurezKabelu +
                    "<br><b style=\"color:#00A36C\">Počet a typ spojek:</b> " + pocetTypSpojek +
                    "<br><b style=\"color:#00A36C\">Materiál spojek:</b> " + this.materialSpojek + "</b>" +
                    "<br><b style=\"color:#00A36C\">Rok instalace spojek: </b>" + this.rokInstalaceSpojek + "</b>" +
                    "<br><b style=\"color:#808000\">Zátěž: </b>" + zatez + "</b> %" +
                    "<br><b style=\"color:#808000\">Zemnění: </b>" + this.zemneni + "</b>" +
                    "<br><b style=\"color:#808000\">BLE Tx/Rx: </b>" + tx + "<b>/</b>" + rx +
                    "<br><b>Koeficient:</b><b style=\"color:blue\"> " + this.koeficient + "</b>";
                break;
            case "MW":
                let rxMHz = this.rxMHz;
                let txMHz = this.txMHz;
                let bandwithMHz = this.bandwithMHz;

                if (rxMHz <= 0) rxMHz = "<b style=\"color:red\">-</b>";
                if (txMHz <= 0) txMHz = "<b style=\"color:red\">-</b>";
                if (bandwithMHz <= 0) bandwithMHz = "<b style=\"color:red\">-</b>";
                text = text + "<br><b style=\"color:#4863A0\">Rx: </b>" + rxMHz + " MHz" +
                    "<br><b style=\"color:#00A36C\">Tx: </b>" + txMHz + " MHz" +
                    "<br><b>Bandwidth: </b>" + bandwithMHz + " MHz" +
                    "<br><b>Modulace: </b>" + this.modulace;
                break;

            // PŘIDÁNÍ VÝPISU PRO SPECIFICKOU TECHNOLOGII
        }

        

        if (this.poznamka != "") {
            let poznamka = "<br><b><i>Poznamka:</b> " + this.poznamka + "</i>";
            text = text + poznamka;
        }
        return text;
    }

    static vytvoritSpojeSQL(mnozinaObjektu) {

        var vytvoreneObjekty = [];
        for (let i = 0; i < mnozinaObjektu.length; i++) {
            let nazev = mnozinaObjektu[i].Nazev;
            let A = undefined; let B = undefined;
            let topologie = mnozinaObjektu[i].Topologie;
            let typ = mnozinaObjektu[i].Typ;
            let download = mnozinaObjektu[i].Download;
            let upload = mnozinaObjektu[i].Upload;
            let poznamka = mnozinaObjektu[i].Poznamka;
            let vzdalenost = mnozinaObjektu[i].Vzdalenost;
            let oznaceni = mnozinaObjektu[i].Oznaceni;


            // Spárujeme název stanice s odpovídajícím objektem stanice
            poleStanic.forEach(stanice => {
                if (A == undefined && stanice.nazev == mnozinaObjektu[i].StaniceA && stanice.nazevTopologie == topologie) A = stanice;
                if (B == undefined && stanice.nazev == mnozinaObjektu[i].StaniceB && stanice.nazevTopologie == topologie) B = stanice;
            });

            let novySpoj = new Spoj(A, B, typ, topologie);
            novySpoj.download = download;
            novySpoj.upload = upload;
            novySpoj.poznamka = poznamka;
            novySpoj.oznaceni = oznaceni;
            novySpoj.vzdalenost = vzdalenost;

            switch (typ) {
                case "BPL":
                    novySpoj.koeficient = mnozinaObjektu[i].Koeficient;
                    novySpoj.pocetSpojek = mnozinaObjektu[i].PocetSpojek;
                    novySpoj.typSpojek = mnozinaObjektu[i].TypSpojek;
                    novySpoj.rokInstalaceSpojek = mnozinaObjektu[i].RokInstalaceSpojek;
                    novySpoj.typKabelu = mnozinaObjektu[i].TypKabelu;
                    novySpoj.rokInstalaceKabelu = mnozinaObjektu[i].RokInstalaceKabelu;
                    novySpoj.rx = mnozinaObjektu[i].Rx;
                    novySpoj.tx = mnozinaObjektu[i].Tx;

                    novySpoj.delkaUsekuKabelu = mnozinaObjektu[i].DelkaUsekuKabelu;
                    novySpoj.prurezKabelu = mnozinaObjektu[i].PrurezKabelu;
                    novySpoj.materialSpojek = mnozinaObjektu[i].MaterialSpojek;
                    novySpoj.zatez = mnozinaObjektu[i].Zatez;
                    novySpoj.zemneni = mnozinaObjektu[i].Zemneni;
                    break;
                case "MW":
                    novySpoj.rxMHz = mnozinaObjektu[i].RxMHz;
                    novySpoj.txMHz = mnozinaObjektu[i].TxMHz;
                    novySpoj.bandwithMHz = mnozinaObjektu[i].BandwithMHz;
                    novySpoj.modulace = mnozinaObjektu[i].Modulace;
                    break;

                // PŘIDÁNÍ OBSLUHY PRO SPECIFICKOU TECHNOLOGII
            }


            vytvoreneObjekty.push(novySpoj);
        }
        return vytvoreneObjekty;
    }


}


export class Koeficient {
    constructor(Constants, spoj, doporuceni) {
        if (spoj.typ != "BPL" && spoj.typ == "Koeficient")return;
        let datum = new Date();
        let rok = datum.getFullYear();
        let cisla;

        this.doporuceni = "";

        this.vzdalenost = Constants.KOEF_VZDALENOST;
        this.stariKabelu = Constants.KOEF_STARI_KABELU;
        this.typKabelu = Constants.KOEF_TYP_KABELU;
        this.prurezKabelu = Constants.KOEF_PRUREZ_KABELU;
        this.pocetSpojek = Constants.KOEF_POCET_SPOJEK;
        this.stariSpojky = Constants.KOEF_STARI_SPOJEK;
        this.typSpojky = Constants.KOEF_TYP_SPOJEK;
        this.zatez = Constants.KOEF_ZATEZ;
        this.zemneni = Constants.KOEF_ZEMNENI;
        this.propustnost = Constants.KOEF_PROPUSTNOST;

        if (spoj.vzdalenost > 0) this.vzdalenost = ((spoj.vzdalenost * 1000) / 1200) * Constants.KOEF_VZDALENOST;
        if (this.vzdalenost > Constants.KOEF_VZDALENOST) this.vzdalenost = Constants.KOEF_VZDALENOST;
        if (this.vzdalenost < 0) this.vzdalenost = 0;


        //Regulární výraz /d+/g znamená "hledat jedno nebo více po sobě jdoucích čísel" a g znamená "globálně" (tj. hledat v celém řetězci, nikoli jen první shodu). 
        //Metoda match() pak vrátí pole nalezených shod.
        if (spoj.rokInstalaceKabelu != undefined && spoj.rokInstalaceKabelu.length > 0) {
            if (spoj.rokInstalaceKabelu.toUpperCase().includes("NEZADÁNO") || spoj.rokInstalaceKabelu.toUpperCase().includes("NEUVEDENO") || spoj.rokInstalaceKabelu.toUpperCase().includes("NE")) {
                if (doporuceni) this.doporuceni = this.doporuceni + "Neznámé stáří kabelové trasy. ";
            }
            else {
                cisla = spoj.rokInstalaceKabelu.match(/\d+/g);
                if (cisla != undefined && cisla.length > 0) {
                    cisla.sort(function (a, b) {
                        return a - b;
                    });

                    if (rok - cisla[0] < 40) {
                        this.stariKabelu = 0;
                    } else {
                        if (doporuceni) this.doporuceni = this.doporuceni + "Část kabelové trasy je příliš stará. ";
                    }

                }
            }
        } else {
            if (doporuceni) this.doporuceni = this.doporuceni + "Stáří kabelové trasy nebylo zadáno. ";
        }



        if (spoj.typKabelu != undefined && spoj.typKabelu.length > 0) {
            if (spoj.typKabelu.toUpperCase().includes("NEZADÁNO") || spoj.typKabelu.toUpperCase().includes("NEUVEDENO") || spoj.typKabelu.toUpperCase().includes("NE")) {
                if (doporuceni) this.doporuceni = this.doporuceni + "Neznámý typ kabelu. ";
            }
            else {
                let typKabelu = undefined;
                for (let i = 0; i < Constants.PILC.length; i++) {
                    if (spoj.typKabelu.toLowerCase().includes(Constants.PILC[i].toLowerCase())) {
                        typKabelu = 1;
                        if (doporuceni) this.doporuceni = this.doporuceni + "Nevhodný typ kabelu. ";
                        break;
                    }
                }
                if (typKabelu == undefined) this.typKabelu = 0;

            }
        } else {
            if (doporuceni) this.doporuceni = this.doporuceni + "Typ kabelu nebyl zadán. ";
        }



        if (spoj.prurezKabelu >= 50) this.prurezKabelu = ((630 - spoj.prurezKabelu) / (630 - 50)) * Constants.KOEF_PRUREZ_KABELU;
        if (this.prurezKabelu < 0) this.prurezKabelu = 0;
        if (this.prurezKabelu != 0) {
            if (doporuceni) this.doporuceni = this.doporuceni + "Zvětšit průřez kabelu. ";
        }


        if (spoj.pocetSpojek != "") {
            if (spoj.pocetSpojek >= 0) {
                this.pocetSpojek = (spoj.pocetSpojek / 20) * Constants.KOEF_POCET_SPOJEK;
                if (doporuceni) this.doporuceni = this.doporuceni + "Zmenšit počet spojek na trase. ";
            }
            if (this.pocetSpojek > Constants.KOEF_POCET_SPOJEK) this.pocetSpojek = Constants.KOEF_POCET_SPOJEK
        } else {
            if (doporuceni) this.doporuceni = this.doporuceni + "Počet spojek na trase nebyl zadán. ";
        }

        if (spoj.pocetSpojek != "") {
            if (spoj.pocetSpojek > 0) {
                if (spoj.rokInstalaceSpojek != undefined && spoj.rokInstalaceSpojek.length > 0) {
                    cisla = spoj.rokInstalaceSpojek.match(/\d+/g);
                    if (cisla != undefined && cisla.length >= spoj.pocetSpojek) {
                        cisla.sort(function (a, b) {
                            return a - b;
                        });

                        if (rok - cisla[0] < 40) this.stariSpojky = 0;
                    } else {
                        if (doporuceni) this.doporuceni = this.doporuceni + "Neznámý rok instalace spojek. ";
                    }
                } else {
                    if (doporuceni) this.doporuceni = this.doporuceni + "Rok instalace spojek nebyl zadán. ";
                }
            } else if (spoj.pocetSpojek == 0) this.stariSpojky = 0;
        }

        if (spoj.pocetSpojek != "") {
            if (spoj.pocetSpojek > 0) {
                if (spoj.typSpojek != undefined && spoj.typSpojek.length > 0) {
                    if (spoj.typSpojek.toUpperCase().includes("NEZADÁNO") || spoj.typSpojek.toUpperCase().includes("NEUVEDENO") || spoj.typSpojek.toUpperCase().includes("NE")) {
                        if (doporuceni) this.doporuceni = this.doporuceni + "Neznámý typ spojek. ";
                    }
                    else {
                        if (spoj.typSpojek.includes("smrš") || spoj.typSpojek.includes("smršťovací")) {
                            if (doporuceni) this.doporuceni = this.doporuceni + "Nevhodný typ spojek. ";
                        }
                        else if (spoj.typSpojek.includes("plast") || spoj.typSpojek.includes("plastová")) this.typSpojky = 0;
                    }
                } else {
                    if (doporuceni) this.doporuceni = this.doporuceni + "Typ spojek nebyl zadán. ";
                }
            } else if (spoj.pocetSpojek == 0) this.typSpojky = 0;
        }

        if (spoj.zatez.length > 0) {
            if (spoj.zatez >= 0) {
                this.zatez = (spoj.zatez / 100) * Constants.KOEF_ZATEZ;
                if (doporuceni) this.doporuceni = this.doporuceni + "Zmenšit zátěž trasy. ";
            }
            if (this.zatez > 0.035) this.zatez = Constants.KOEF_ZATEZ;
        } else {
            if (doporuceni) this.doporuceni = this.doporuceni + "Zátěž trasy nezadána. ";
        }



        if (spoj.zemneni != undefined && spoj.zemneni != "") {
            if (spoj.zemneni.includes("NEZADÁNO") || spoj.zemneni.includes("Není uvedeno")) {
                if (doporuceni) this.doporuceni = this.doporuceni + "Neznámý způsob zemnění. ";
            }
            else {
                if (spoj.zemneni.includes(Constants.ZEMNENI[0]) || spoj.zemneni.includes(Constants.ZEMNENI[1]) || spoj.zemneni.includes(Constants.ZEMNENI[2])) {
                    if (doporuceni) this.doporuceni = this.doporuceni + "Nevhodný způsob zemnění. ";
                }
                else this.zemneni = 0;
            }
        }

        if (spoj.download > 0) this.propustnost = ((50 - spoj.download) / 50) * Constants.KOEF_PROPUSTNOST;
        if (this.propustnost < 0) this.propustnost = 0;

        this.value = 1 - this.vzdalenost - this.stariKabelu - this.typKabelu - this.prurezKabelu - this.pocetSpojek - this.stariSpojky - this.typSpojky - this.zatez - this.zemneni - this.propustnost;
        if (Constants.ROUNDKOEF >= 0) this.value = this.value.toFixed(Constants.ROUNDKOEF);

        if (this.value <= 0) {
            this.value = 0;
        }
    }
}

export class Soubor {

    constructor(jmeno, datum) {
        // Obecne parametry
        this.nazev = jmeno;
        this.datum = datum;
        // Pro potřeby tabulky
        this.radek;

        // Soubor je uložen do pole a to je setřízeno
        poleSouboru.push(this);
        Soubor.vytridit();
    }

    static vytridit() {
        poleSouboru.sort(function (a, b) {
            var dateA = new Date(a.datum);
            var dateB = new Date(b.datum);
            return dateB - dateA;
        });
    }

    static vytvoritSouborySQL(mnozinaSouboru) {
        var vytvoreneSoubory = [];
        for (let i = 0; i < mnozinaSouboru.length; i++) {
            let nazev = mnozinaSouboru[i].nazev;
            let datum = mnozinaSouboru[i].datum;

            let novySoubor = new Soubor(nazev, datum);

            vytvoreneSoubory.push(novySoubor);
        }
        return vytvoreneSoubory;
    }
}


