/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package vypocetObalky;

import com.javadocmd.simplelatlng.LatLng;
import com.javadocmd.simplelatlng.LatLngTool;
import com.javadocmd.simplelatlng.util.LengthUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

/**
 *
 * @author Filip Dvorak
 */
class Vypocty {
    
    //jednoZpozdeniKOrientacnimuBodu je to zpozdeni se ktery aktualne pocitame
    // aktualniSouradnice --- to jsou souradnice uzlu na kterem to bezi    

    public static ArrayList<ZpozdeniKOrientacnimuBodu> VypocetVzdalenostiKOrientacnimBodum(Souradnice aktualniSouradnice, ArrayList<ZpozdeniKOrientacnimuBodu> zpozdeniKOrientacnimBodum) {

        for (ZpozdeniKOrientacnimuBodu aktualniZpozdeniAVzdalenostKOrientacnimuBodu : zpozdeniKOrientacnimBodum) {
            double vzdalenostKOrientacnimuBodu = VypoctiVzdalenostKOrientacnimuBodu(aktualniSouradnice, aktualniZpozdeniAVzdalenostKOrientacnimuBodu);
            aktualniZpozdeniAVzdalenostKOrientacnimuBodu.setVzdalenost(vzdalenostKOrientacnimuBodu);
            //System.out.println("Vypocet vzdalenosti : " + jednoZpozdeniKOrientacnimuBodu.getVzdalenost());
            System.out.println(aktualniZpozdeniAVzdalenostKOrientacnimuBodu.getVzdalenost());
        }

        return zpozdeniKOrientacnimBodum;
    }

    private static double VypoctiVzdalenostKOrientacnimuBodu(Souradnice aktualniSouradnice, ZpozdeniKOrientacnimuBodu jednoZpozdeniKOrientacnimuBodu) {
        // vypocet opravdove zemepisne vzdalenosti podle:
        // http://stackoverflow.com/questions/120283/working-with-latitude-longitude-values-in-java

        //knihovna pro geo vypocet
        //LatLng bodA = new LatLng(aktualniSouradnice.getSouradniceX(), aktualniSouradnice.getSouradniceY());
        //LatLng bodB = new LatLng(jednoZpozdeniKOrientacnimuBodu.getOrientacniBod().getSouradnice().getSouradniceX(), jednoZpozdeniKOrientacnimuBodu.getOrientacniBod().getSouradnice().getSouradniceY());
        //double vzd = LatLngTool.distance(bodA, bodB, LengthUnit.KILOMETER);



        //souradnice aktualniho uzlu
        double aSirka = aktualniSouradnice.getSouradniceX();
        double aDelka = aktualniSouradnice.getSouradniceY();
        //souradnice vzdaleneho orientacniho uzlu
        double bSirka = jednoZpozdeniKOrientacnimuBodu.getOrientacniBod().getSouradnice().getSouradniceX();
        double bDelka = jednoZpozdeniKOrientacnimuBodu.getOrientacniBod().getSouradnice().getSouradniceY();

        double polomerZeme = 6368.5;
        double souradniceNaZemiSirka = Math.toRadians(bSirka - aSirka);
        double souradniceNaZemiDelka = Math.toRadians(bDelka - aDelka);
        double a = Math.sin(souradniceNaZemiSirka / 2) * Math.sin(souradniceNaZemiSirka / 2) + Math.cos(Math.toRadians(aSirka))
                * Math.cos(Math.toRadians(bSirka)) * Math.sin(souradniceNaZemiDelka / 2)
                * Math.sin(souradniceNaZemiDelka / 2);

        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        //double vzdalenostKOrientacnimuBodu = Math.sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by));
        double vzdalenostKOrientacnimuBodu = polomerZeme * c;
        //vzdalenost je v km
        return vzdalenostKOrientacnimuBodu;
        //return vzd;
    }

    //fukce vytvori graf --- tzv. obalka ve ktere jsou zahrnuty vsechny body --->z obalky je pozdeji zjisten pomer zpozdeni/vzdalenost
    public static ArrayList<Souradnice> vytvorGraf(ArrayList<ZpozdeniKOrientacnimuBodu> zpozdeniKOrientacnimBodum) {
        //velikost pole - počet aktuálně uložených prvků
        ArrayList<Souradnice> graf = new ArrayList<Souradnice>(zpozdeniKOrientacnimBodum.size());
        

        //vlozi nulove souradnice na zacatek pole
        graf.add(new Souradnice(0.0, 0.0));
        for (ZpozdeniKOrientacnimuBodu jednoZpozdeniKOrientacnimuBodu : zpozdeniKOrientacnimBodum) {
            graf.add(new Souradnice(jednoZpozdeniKOrientacnimuBodu.getVzdalenost(), jednoZpozdeniKOrientacnimuBodu.getZpozdeni()));
        }
        //serazeni podle osy X
        Collections.sort(graf, Porovnavace.podleOsyX());
        return graf;
    }

    //vypocet usecky
    private static Primka vypoctiPrimku(Souradnice a, Souradnice b) {
        double k = (b.getSouradniceY() - a.getSouradniceY()) / (b.getSouradniceX() - a.getSouradniceX());
        double q = a.getSouradniceY() - k * a.getSouradniceX();
        Primka primka = new Primka(k, q, a, b);
        return primka;
    }



    public static ArrayList<ZpozdeniKOrientacnimuBodu> vyradNulovePingy(ArrayList<ZpozdeniKOrientacnimuBodu> zpozdeniKOrientacnimBodum) {
        ArrayList<ZpozdeniKOrientacnimuBodu> zpozdeniKOrientacnimBodumNove = new ArrayList<ZpozdeniKOrientacnimuBodu>();
        int k = 0;
        for (ZpozdeniKOrientacnimuBodu aktualniZpozdeniKOrientacnimuBodu : zpozdeniKOrientacnimBodum) {
            if (aktualniZpozdeniKOrientacnimuBodu.getZpozdeni() != 0.0) {
                zpozdeniKOrientacnimBodumNove.add(aktualniZpozdeniKOrientacnimuBodu);
            } else {
                k++;
            }
        }
        System.out.println("Pocet uzlu, ktere neodpovedeli dotazu ping :" + k);
        Log.zapisDoLogu("Pocet uzlu, ktere neodpovedeli dotazu ping :" + k);

        return zpozdeniKOrientacnimBodumNove;
    }

    public static ArrayList<ZpozdeniKOrientacnimuBodu> vyradNuloveVzdalenosti(ArrayList<ZpozdeniKOrientacnimuBodu> zpozdeniKOrientacnimBodumBezNulovychPing) {
        ArrayList<ZpozdeniKOrientacnimuBodu> zpozdeniKOrientacnimBodumNove = new ArrayList<ZpozdeniKOrientacnimuBodu>();
        int k = 0;
        for (ZpozdeniKOrientacnimuBodu aktualniZpozdeniKOrientacnimuBodu : zpozdeniKOrientacnimBodumBezNulovychPing) {
            if (aktualniZpozdeniKOrientacnimuBodu.getVzdalenost() != 0.0) {
                zpozdeniKOrientacnimBodumNove.add(aktualniZpozdeniKOrientacnimuBodu);
            } else {
                k++;
            }
        }
        System.out.println("Pocet uzlu, ktere maji nulovou vzdalenost :" + k);
        Log.zapisDoLogu("Pocet uzlu, ktere maji nulovou vzdalenost  :" + k);

        return zpozdeniKOrientacnimBodumNove;
    }

    public static ArrayList<ZpozdeniKOrientacnimuBodu> vyradStejneIP(ArrayList<ZpozdeniKOrientacnimuBodu> zpozdeniKOrientacnimBodumBezNulovychPingANulovychVzdalenosti) {
        ArrayList<ZpozdeniKOrientacnimuBodu> zpozdeniKOrientacnimBodumNove = new ArrayList<ZpozdeniKOrientacnimuBodu>();
        int k = 0;
        for (ZpozdeniKOrientacnimuBodu aktualniOrientacniBod : zpozdeniKOrientacnimBodumBezNulovychPingANulovychVzdalenosti) {
            for (int i = 0; i < zpozdeniKOrientacnimBodumBezNulovychPingANulovychVzdalenosti.size(); i++) {
                if (aktualniOrientacniBod.getOrientacniBod().getSouradnice().getSouradniceX() != zpozdeniKOrientacnimBodumBezNulovychPingANulovychVzdalenosti.get(i).getOrientacniBod().getSouradnice().getSouradniceX()) {
                    zpozdeniKOrientacnimBodumNove.add(aktualniOrientacniBod);
                } else {
                    k++;
                }
            }
        }
        System.out.println("Pocet uzlu, ktere maji stejnou IP :" + k);
        Log.zapisDoLogu("Pocet uzlu, ktere maji stejnou IP  :" + k);

        return zpozdeniKOrientacnimBodumNove;
    }


    public static ArrayList<Souradnice> vyradStejneSouradnice(ArrayList<Souradnice> grafH) {
        ArrayList<Souradnice> pomocnyGraf = new ArrayList<Souradnice>();
        pomocnyGraf.add(grafH.get(0));
        grafH.remove(0);
        //pomocna promenna, ktera zajisti nezapsani prvku do pole pomocnyGraf
        boolean jeZdeStejnyPrvek = false;
        //cyklus pro prohledani pole grafH
        for (Souradnice aktualnisouradnice : grafH) {
            jeZdeStejnyPrvek = false;
            //cyklus pro prohledani pole pomocny graf
            for (Souradnice pomocneSouradnice : pomocnyGraf) {
                //vyradi body se stejnymi souradnicemi x,y a zaroven vyradi hodnoty ping vetsich nez 250ms --- tyto hodnoty zkreslovaly vysledny graf
                if (aktualnisouradnice.getSouradniceX().intValue() == pomocneSouradnice.getSouradniceX().intValue()) {
                    jeZdeStejnyPrvek = true;
                    break;
                } else if (aktualnisouradnice.getSouradniceY().intValue() > 250) {
                    jeZdeStejnyPrvek = true;
                    break;
                }

            }
            if (jeZdeStejnyPrvek == false) {
                // zapise hodnotu do pole pomocny graf
                pomocnyGraf.add(aktualnisouradnice);
            }
        }
        return pomocnyGraf;
    }


    public static ArrayList<Souradnice> vyradRychlejsiBody(ArrayList<Souradnice> grafNovy) {
        ArrayList<Souradnice> grafPomocny = new ArrayList<Souradnice>();

        Souradnice a = new Souradnice(0.0, 0.0);
        //Souradnice b = new Souradnice(299792.458,1000.0 );
        Souradnice b = new Souradnice(100.0, 1.0);
        Primka rychlostSvetla = vypoctiPrimku(a, b);

        for (Souradnice aktualniSouradnice : grafNovy) {
            //body jsou pod primkou prave kdyz kazdy bod ma y souradnici mensi nebo rovnu vypoctene hodnote
            //ze smernicove rovnice primky y = kx + q

            Double bodX = aktualniSouradnice.getSouradniceX();
            Double bodY = aktualniSouradnice.getSouradniceY();

            Double k = rychlostSvetla.getK();
            Double q = rychlostSvetla.getQ();

            Double primkaY = (k * bodX) + q;
            //pokud bod lezi nad primkou tak se ulozi
            if (bodY >= primkaY) {
                grafPomocny.add(aktualniSouradnice);
            }
        }
        return grafPomocny;
    }

    private static class Porovnavace {

        public static class podleOsyXTrida implements Comparator<Souradnice> {

            @Override
            //metoda compare s parametry typu souradnice
            //vrati porovnane pole souradnic podle x souradnic
            public int compare(Souradnice s1, Souradnice s2) {

                double rozdil = (s1.getSouradniceX() - s2.getSouradniceX());
                //porovnani hodnot - ktera je vetsi kdyz je S2 vetsi nez S1 ---- 1

                if (rozdil > 0.0) {
                    return 1;
                } else if (rozdil < 0.0) {
                    return -1;
                } else {
                    return 0;
                }

            }
        }

        public static Comparator<Souradnice> podleOsyX() {
            return new podleOsyXTrida();
        }
    }
}
