package app.GUI;


import app.DataUtil;
import app.PREDICTION.CH4ConsumptionPredictor;
import app.PREDICTION.GasConsumptionPredictor;
import app.PREDICTION.OilConsuptionPredictor;
import app.PREPROCESSING.PrepConf;
import app.PREPROCESSING.Preprocesor;
import org.primefaces.model.chart.*;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import java.util.ArrayList;
import java.util.List;


/**
 * Created by Petr Flégl on 20.1.2017.
 */
@Named
@RequestScoped

public class OverView {

    GasConsumptionPredictor gcp ;
    OilConsuptionPredictor ocp;
    CH4ConsumptionPredictor acp;

    //promenna pro model grafu, tak aby se dala v overview.xhtml vyzadat a napasovat na graf
    private LineChartModel gasPrediction;
    private LineChartModel oilPrediction;
    private LineChartModel anPrediction;



    //...pro model parametru predikce, asi String slozeny ze vsech casti pri getPopisek
    double[] gcpBetas, ocpBetas, acpBetas;
    String oilEquation = "";
    String gasEquation = "";



    String anaEquation = "";

    //... pro model vysledku predikce jako data pro tabulku
    private static int NUM_OF_DAYS = 6;
    double[] gcpPredictionValues = new double[NUM_OF_DAYS];
    double[] ocpPredictionValues = new double[NUM_OF_DAYS];
    double[] acpPredictionValues = new double[NUM_OF_DAYS];





    public OverView(){
        //TODO vratit zpet aktualni rok (0) misto dvou let zpet (2)
       // int bto = DataUtil.dateToTimestamp(DataUtil.getDay(0),DataUtil.getMonth(1),DataUtil.getYear(2)) ;
        int bto = DataUtil.dateToTimestamp("1-11-2015", "-");
        //int bfrom = DataUtil.dateToTimestamp(DataUtil.getDay(48),DataUtil.getMonth(1),DataUtil.getYear(2)) ;
        int bfrom = DataUtil.dateToTimestamp("14-9-2015", "-");
        int xyears = 2;

        bto = /*DataUtil.getTimestampForDay(0)*/(DataUtil.dateToTimestamp(31,12,2015));
        //System.out.println("BTO" +bto);
        bfrom=DataUtil.dateToTimestamp(1,1,2016)-((DataUtil.getTimestampForDay(0)-DataUtil.getTimestampForDay(55)));
        //System.out.println("BFROM" +bfrom);
        gcp = new GasConsumptionPredictor(bfrom,bto,xyears);
       // bto = /*DataUtil.getTimestampForDay(0)*/(DataUtil.dateToTimestamp(31,12,2015));
        bfrom=DataUtil.dateToTimestamp(1,1,2016)-(DataUtil.getTimestampForDay(0)-DataUtil.getTimestampForDay(25));
        acp = new CH4ConsumptionPredictor(bfrom,bto,xyears);

        ocp = new OilConsuptionPredictor(60);

        initModelParamTable();
        initModelResultTable();
        initGraph();

    }

    public void initGraph(){


        gasPrediction = gasPredictionGraf();
        gasPrediction.setTitle("Predikce spotreby plynu");
        gasPrediction.setLegendPosition("e");
        gasPrediction.getAxes().put(AxisType.X, new CategoryAxis(""));
        Axis yAxis = gasPrediction.getAxis(AxisType.Y);
        gasPrediction.setSeriesColors("58BA27,FFCC33,F74A4A,F52F2F,A30303");

        oilPrediction = oilPredictionGraf();
        oilPrediction.setTitle("Predikce oil");
        oilPrediction.setLegendPosition("e");
        oilPrediction.getAxes().put(AxisType.X, new CategoryAxis(""));
        yAxis = oilPrediction.getAxis(AxisType.Y);
        oilPrediction.setSeriesColors("58BA27,F74A4A,F52F2F,A30303");

        anPrediction = anPredictionGraf();
        anPrediction.setTitle("Predikce analyzy plynu");
        anPrediction.setLegendPosition("e");
        anPrediction.getAxes().put(AxisType.X, new CategoryAxis(""));
        yAxis = anPrediction.getAxis(AxisType.Y);
        anPrediction.setSeriesColors("58BA27,F74A4A,F52F2F,A30303");

    }

    String[] measuredLabel = {"0","-1","-2","-3","-4","-5","-6","-7","-8","-9","-10"};
    String[] predictionLabel = {"+1","+2","+3","+4","+5","+6","+7"};

    private LineChartModel gasPredictionGraf() {
        LineChartModel bio = new LineChartModel();
        List<LineChartSeries> dataList = new ArrayList<>();
        List<PrepConf> dataConf = new ArrayList<>();
        LineChartSeries sm = new LineChartSeries();
        sm.setLabel("Predchozi");
        LineChartSeries sc = new LineChartSeries();
        sc.setLabel("Ze substratu");

            dataConf.add(new PrepConf("table4:spotrebaPlynu", "spotreba", "datumBio", gcp.getTimestampBetaFrom()-(60*60*24*5), gcp.getTimestampBetaFrom(), 0, 1500, 0, 1500));
        dataConf.add(new PrepConf("table2:celkVytez", "vyteznost ze substratu vypoctena", "datumVytez", gcp.getTimestampBetaFrom()-(60*60*24*5), gcp.getTimestampBetaFrom(), 0, 1500, 0, 1500));
            Preprocesor p = new Preprocesor(dataConf);
            double vals[][] = p.getData();  //2 sloupec, nekolik radku podle rozmezi casu
            dataConf.clear();

        if(vals.length>0)
            for(int row=0;row<vals[0].length;row++) {
                sm.set(measuredLabel[row], vals[0][row]);
                sc.set(measuredLabel[row], vals[1][row]);
            }
        dataList.add(sm);
        dataList.add(sc);
        if(gcpBetas.length==6){
            LineChartSeries sp = new LineChartSeries();
            sp.setLabel("Predikce");
            for (int d=0;d<NUM_OF_DAYS;d++) {
                sp.set(predictionLabel[d], gcpPredictionValues[d]);
            }
            dataList.add(sp);
        }
        for (LineChartSeries s: dataList) {
            bio.addSeries(s);
        }
        return bio;
    }

    private LineChartModel oilPredictionGraf() {
        LineChartModel oil = new LineChartModel();
        List<LineChartSeries> dataList = new ArrayList<>();
        List<PrepConf> dataConf = new ArrayList<>();
        LineChartSeries sm = new LineChartSeries();
        sm.setLabel("Predchozi");

        dataConf.add(new PrepConf("table9:dobaOleje", "Olej", "idOlej", ocp.getId()-5, ocp.getId()+1, 0, 1500, 0, 1500));
        Preprocesor p = new Preprocesor(dataConf);
        double vals[][] = p.getData();
        dataConf.clear();

        if(vals.length>0)
            for(int row=0;row<vals[0].length;row++) {
                sm.set(measuredLabel[row], vals[0][row]);
            }
        dataList.add(sm);

        if(ocpBetas.length==5) {
            LineChartSeries sp = new LineChartSeries();
            sp.setLabel("Predikce");
                sp.set(predictionLabel[0], ocpPredictionValues[0]);
            sp.setMarkerStyle("+");
            dataList.add(sp);
        }

        for (LineChartSeries s: dataList) {
            oil.addSeries(s);
        }
        return oil;
    }


    private LineChartModel anPredictionGraf() {
        LineChartModel plyn = new LineChartModel();
        List<LineChartSeries> dataList = new ArrayList<>();
        List<PrepConf> dataConf = new ArrayList<>();
        LineChartSeries sm = new LineChartSeries();
        sm.setLabel("predchozi");

        dataConf.add(new PrepConf("table5:metan", "metan", "datumPlyn", gcp.getTimestampBetaFrom()-(60*60*24*5), gcp.getTimestampBetaFrom(), 0, 1500, 0, 1500));

        Preprocesor p = new Preprocesor(dataConf);
        double vals[][] = p.getData();
        dataConf.clear();

        if(vals.length>0)
            for(int row=0;row<vals[0].length;row++) {
                sm.set(measuredLabel[row], vals[0][row]);
            }

        dataList.add(sm);

        if(acpBetas.length==4){
            LineChartSeries sp = new LineChartSeries();
            sp.setLabel("Predikce");
            for (int d=0;d<NUM_OF_DAYS;d++)
                sp.set(predictionLabel[d],acpPredictionValues[d]);
            dataList.add(sp);
        }

        for (LineChartSeries s: dataList) {
            plyn.addSeries(s);
        }
        return plyn;
    }
    public void initModelResultTable(){
        gcpPredictionValues = gcp.getResults(NUM_OF_DAYS);
        ocpPredictionValues = ocp.getResults(50);
        acpPredictionValues = acp.getResults(NUM_OF_DAYS);
    }

    public void initModelParamTable(){
        gcpBetas = gcp.getBetaArray();
        ocpBetas = ocp.getBetaArray();
        acpBetas = acp.getBetaArray();
    }

    public LineChartModel getGasPrediction() {
        return gasPrediction;
    }

    public LineChartModel getOilPrediction() { return oilPrediction; }

    public LineChartModel getAnPrediction() { return anPrediction; }

    public void setGasPrediction(LineChartModel gasPrediction) {
        this.gasPrediction = gasPrediction;
    }

    public void setOilPrediction(LineChartModel oilPrediction) { this.oilPrediction = oilPrediction; }

    public void setAnPrediction(LineChartModel anPrediction) { this.anPrediction = anPrediction; }


    public double[] getGcpBetas() {
        return gcpBetas;
    }

    public void setGcpBetas(double[] gcpBetas) {
        this.gcpBetas = gcpBetas;
    }

    public double[] getOcpBetas() {
        return ocpBetas;
    }

    public void setOcpBetas(double[] ocpBetas) {
        this.ocpBetas = ocpBetas;
    }

    public double[] getAcpBetas() {
        return acpBetas;
    }

    public void setAcpBetas(double[] acpBetas) {
        this.acpBetas = acpBetas;
    }

    public String getOilEquation() {
        if(ocpBetas.length==5)
            oilEquation = "Parametry predikce oleje: y="+r(ocpBetas[0])+"+"+r(ocpBetas[1])+"*x1+"+r(ocpBetas[2])+"*x2+"+r(ocpBetas[3])+"*x3+"+r(ocpBetas[4])+"*x4";
        else
            oilEquation = "Parametry predikce nenalezeny";


        return oilEquation;
    }

    public void setOilEquation(String oilEquation) {
        this.oilEquation = oilEquation;
    }

    public String getGasEquation() {
        if(gcpBetas.length==6)
            gasEquation = "Parametry predikce spotreby plynu: y="+r(gcpBetas[0])+"+"+r(gcpBetas[1])+"*x1+"+r(gcpBetas[2])+"*x2+"+r(gcpBetas[3])+"*x3+"+r(gcpBetas[4])+"*x4+"+r(gcpBetas[5])+"*x5";
        else
            gasEquation = "Parametry predikce nenalezeny";

        return gasEquation;

    }

    public void setGasEquation(String gasEquation) {
        this.gasEquation = gasEquation;
    }

    public String getAnaEquation() {

        if(acpBetas.length==4)
            anaEquation = "Parametry predikce metanu: y="+r(acpBetas[0])+"+"+r(acpBetas[1])+"*x1+"+r(acpBetas[2])+"*x2+"+r(acpBetas[3])+"*x3";
        else
            anaEquation = "Parametry predikce nenalezeny";

        return anaEquation;

    }

    public void setAnaEquation(String anaEquation) {
        this.anaEquation = anaEquation;
    }

    private double r(double number){
        return ((double)Math.round(number*1000))/1000;
    }

}
