package main;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.Date;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;

class LoadTestDataARListener implements ActionListener {
    private StartApplet applet;
    private int forecast_AR;
    private double test_error_sum, bendra_suma2, bendra_suma3, bendra_suma4, bendra_suma5;
    private double[] new_array, new_array_AR, forecast_array;
    private String data[][];
    private JPanel test_data_AR_Panel;
    private JLabel MAE_test_AR_Label, MAPE_test_AR_Label, PMAD_test_AR_Label, MSE_test_AR_Label, RMSE_test_AR_Label, residual_variance_test_AR_Label;
    private JLabel MAE_test_value_AR_Label, MAPE_test_value_AR_Label, PMAD_test_value_AR_Label, MSE_test_value_AR_Label, RMSE_test_value_AR_Label, residual_variance_test_value_AR_Label;
    //private JLabel data_mean_test_AR_Label, data_mean_test_value_AR_Label, data_variance_test_AR_Label, data_variance_test_value_AR_Label;
    private JButton save_test_CSV_AR_Button;
    private JScrollPane test_data_AR_Scroll;

    public LoadTestDataARListener(StartApplet applet) {
        this.applet = applet;
    }

    public void actionPerformed(ActionEvent e) {
        applet.test_data_AR_Frame = new JFrame();
        applet.test_data_AR_Frame.setTitle("Test AR data");
        applet.test_data_AR_Frame.setSize(800,600);
        applet.test_data_AR_Frame.setVisible(true);

        String titles[] = new String[4];
        titles[0] = "No.";
        titles[1] = "Actual value";
        titles[2] = "Forecast";
        titles[3] = "Error";

        String forecast_string = applet.forecast_AR_Field.getText();
        int forecast_length = forecast_string.length();
        if ( forecast_length <= 0 ) forecast_AR = 1;
        else forecast_AR = Integer.parseInt( applet.forecast_AR_Field.getText() );

        data = new String[applet.entered_data_Count+forecast_AR][5];

        applet.forecast_test_AR_Series = new TimeSeries( "Forecast", Day.class );

        new_array = new double[applet.entered_data_Count];
        for ( int i = 0; i < applet.entered_data_Count; i++ ) {
            data[i][0] = Integer.toString(i+1) + "."; //numeracija
            data[i][1] = String.valueOf( applet.data_AR_Table.getValueAt(i, 1) ); //realūs duomenys
            new_array[i] = Double.parseDouble( String.valueOf( applet.data_AR_Table.getValueAt(i, 1) ) );
        }

        //test_data_sum = 0;
        //test_data_sum2 = 0;
        test_error_sum = 0;
        bendra_suma2 = 0;
        bendra_suma3 = 0;
        bendra_suma4 = 0;
        bendra_suma5 = 0;

        applet.testing_data_AR_Count = applet.entered_data_Count - Integer.parseInt(applet.training_data_AR_Field.getText());

        int n = 0;
        forecast_array = new double[applet.testing_data_AR_Count];
        for ( int i = applet.training_data_AR_Count; i < applet.entered_data_Count; i++ ) {
            double suma = 0;
            for ( int j = 0; j < applet.coef_AR.length; j++ ) {
                suma += applet.round(applet.coef_AR[j],3) * new_array[i-j-1];
                forecast_array[n] = suma;
            }
            data[i][2] = Double.toString( applet.round(suma, 3) );
            
            //test_data_sum += applet.entered_data_AR[i];
            //test_data_sum2 += applet.entered_data_AR[i]*applet.entered_data_AR[i];

            double error = new_array[applet.training_data_AR_Count+n] - forecast_array[n];
            bendra_suma5 += error;
            if ( error < 0 ) error = error * (-1);
            data[i][3] = Double.toString( applet.round(error, 3) );
            test_error_sum += error;
            bendra_suma2 += error / Double.parseDouble( String.valueOf( applet.data_AR_Table.getValueAt(i, 1) ) );
            bendra_suma3 += Double.parseDouble( String.valueOf( applet.data_AR_Table.getValueAt(i, 1) ) );
            bendra_suma4 += error * error;

            Date now = new Date();
            Calendar cal = Calendar.getInstance();
            cal.setTime(now);
            cal.add(Calendar.DAY_OF_YEAR, i+1);
            Date tomorrow = cal.getTime();
            applet.forecast_test_AR_Series.add( new Day( tomorrow ), applet.round(suma, 3) );
            n++;
        }

        /*int k = 0;
        for ( int i = applet.training_data_AR_Count; i < applet.entered_data_Count; i++ ) {
            double error = new_array[applet.training_data_AR_Count+k] - forecast_array[k];
            bendra_suma5 += error;
            if ( error < 0 ) error = error * (-1);
            data[i][3] = Double.toString( applet.round(error, 3) );
            bendra_suma += error;
            bendra_suma2 += error / Double.parseDouble( String.valueOf( applet.data_AR_Table.getValueAt(i, 1) ) );
            bendra_suma3 += Double.parseDouble( String.valueOf( applet.data_AR_Table.getValueAt(i, 1) ) );
            bendra_suma4 += error * error;
            k++;
        }*/

        new_array_AR = new double[forecast_AR+applet.p_value_AR];
        for ( int i = applet.p_value_AR; i > 0; i-- )
            new_array_AR[applet.p_value_AR-i] = applet.entered_data_AR[applet.entered_data_Count-i];

        applet.forecast_AR_Series.clear();

        int y = 0;
        for ( int i = applet.entered_data_Count; i < applet.entered_data_Count+forecast_AR; i++ ) {
            data[i][0] = Integer.toString(i+1) + ".";
            double suma = 0;
            for ( int j = 0; j < applet.coef_AR.length; j++ )
                suma += applet.round(applet.coef_AR[j],3) * new_array_AR[applet.p_value_AR+y-j-1];
            new_array_AR[applet.p_value_AR+y] = suma;
            data[i][2] = Double.toString( applet.round(suma, 3) );
            Date now = new Date();
            Calendar cal = Calendar.getInstance();
            cal.setTime(now);
            cal.add(Calendar.DAY_OF_YEAR, i+1);
            Date tomorrow = cal.getTime();
            applet.forecast_test_AR_Series.add( new Day( tomorrow ), applet.round(suma,3) );
            y++;
        }

        test_data_AR_Panel = new JPanel();
        test_data_AR_Panel.setLayout(null);
        applet.test_data_AR_Frame.add(test_data_AR_Panel);

        applet.test_data_AR_Table = new JTable(data, titles) {
            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component c = super.prepareRenderer(renderer, row, column);
                if ( row >= applet.training_data_AR_Count ) c.setBackground(new Color(200,221,242));
                else c.setBackground(null);
                return c;
            }
        };
        test_data_AR_Scroll = new JScrollPane(applet.test_data_AR_Table);
        test_data_AR_Scroll.setVerticalScrollBarPolicy(22);
        test_data_AR_Scroll.setBounds(10, 10, 400, 337);
        test_data_AR_Panel.add(test_data_AR_Scroll);

        applet.graphic_AR_Button = new JButton("Graphic");
        applet.graphic_AR_Button.setBounds(10, 355, 90, 20);
        LoadGraphicListener Graphic_Listener = new LoadGraphicListener( applet, "AR test data graphic", 3 );
        applet.graphic_AR_Button.addActionListener(Graphic_Listener);
        test_data_AR_Panel.add(applet.graphic_AR_Button);

        save_test_CSV_AR_Button = new JButton("Save CSV file");
        save_test_CSV_AR_Button.setBounds(110, 355, 120, 20);
        CSVFileSaveListener test_CSV_file_AR_Listener = new CSVFileSaveListener( applet, 3 );
        save_test_CSV_AR_Button.addActionListener(test_CSV_file_AR_Listener);
        test_data_AR_Panel.add(save_test_CSV_AR_Button);

        /*data_mean_test_AR_Label = new JLabel("Data mean");
        data_mean_test_AR_Label.setBounds(10, 380, 300, 20);
        test_data_AR_Panel.add(data_mean_test_AR_Label);

        data_mean_test_value_AR_Label = new JLabel();
        data_mean_test_value_AR_Label.setBounds(300, 380, 300, 20);
        test_data_AR_Panel.add(data_mean_test_value_AR_Label);

        data_variance_test_AR_Label = new JLabel("Data standart");
        data_variance_test_AR_Label.setBounds(10, 405, 300, 20);
        test_data_AR_Panel.add(data_variance_test_AR_Label);

        data_variance_test_value_AR_Label = new JLabel();
        data_variance_test_value_AR_Label.setBounds(300, 405, 300, 20);
        test_data_AR_Panel.add(data_variance_test_value_AR_Label);*/

        MAE_test_AR_Label = new JLabel("Mean absolute error (MAE)");
        MAE_test_AR_Label.setBounds(10, 380, 300, 20);
        test_data_AR_Panel.add(MAE_test_AR_Label);

        MAE_test_value_AR_Label = new JLabel();
        MAE_test_value_AR_Label.setBounds(300, 380, 300, 20);
        test_data_AR_Panel.add(MAE_test_value_AR_Label);

        MAPE_test_AR_Label = new JLabel("Mean absolute percentage error (MAPE)");
        MAPE_test_AR_Label.setBounds(10, 405, 300, 20);
        test_data_AR_Panel.add(MAPE_test_AR_Label);

        MAPE_test_value_AR_Label = new JLabel();
        MAPE_test_value_AR_Label.setBounds(300, 405, 300, 20);
        test_data_AR_Panel.add(MAPE_test_value_AR_Label);

        PMAD_test_AR_Label = new JLabel("Percent mean absolute deviation (PMAD)");
        PMAD_test_AR_Label.setBounds(10, 430, 300, 20);
        test_data_AR_Panel.add(PMAD_test_AR_Label);

        PMAD_test_value_AR_Label = new JLabel();
        PMAD_test_value_AR_Label.setBounds(300, 430, 300, 20);
        test_data_AR_Panel.add(PMAD_test_value_AR_Label);

        MSE_test_AR_Label = new JLabel("Mean squared error (MSE)");
        MSE_test_AR_Label.setBounds(10, 455, 300, 20);
        test_data_AR_Panel.add(MSE_test_AR_Label);

        MSE_test_value_AR_Label = new JLabel();
        MSE_test_value_AR_Label.setBounds(300, 455, 300, 20);
        test_data_AR_Panel.add(MSE_test_value_AR_Label);

        RMSE_test_AR_Label = new JLabel("Root mean squared error (RMSE)");
        RMSE_test_AR_Label.setBounds(10, 480, 300, 20);
        test_data_AR_Panel.add(RMSE_test_AR_Label);

        RMSE_test_value_AR_Label = new JLabel();
        RMSE_test_value_AR_Label.setBounds(300, 480, 300, 20);
        test_data_AR_Panel.add(RMSE_test_value_AR_Label);

        residual_variance_test_AR_Label = new JLabel("Residual variance");
        residual_variance_test_AR_Label.setBounds(10, 505, 300, 20);
        test_data_AR_Panel.add(residual_variance_test_AR_Label);

        residual_variance_test_value_AR_Label = new JLabel();
        residual_variance_test_value_AR_Label.setBounds(300, 505, 300, 20);
        test_data_AR_Panel.add(residual_variance_test_value_AR_Label);

        /*double data_mean = 0;
        data_mean = test_data_sum / n;
        data_mean_test_value_AR_Label.setText(" = " + Double.toString(applet.round(data_mean, 3)));

        double data_variance = 0;
        data_variance = (test_data_sum2 - ((test_data_sum*test_data_sum)/n)) / (n - 1);
        data_variance_test_value_AR_Label.setText(" = " + Double.toString(applet.round(data_variance, 3)));*/

        double MAE = 0;
        if ( test_error_sum == Double.NaN || test_error_sum == Double.POSITIVE_INFINITY || test_error_sum == Double.NEGATIVE_INFINITY )
            MAE = 0;
        else MAE = test_error_sum / applet.testing_data_AR_Count;
        MAE_test_value_AR_Label.setText( " = " + Double.toString( applet.round(MAE, 3) ) );

        double MAPE = 0;
        if ( bendra_suma2 == Double.NaN || bendra_suma2 == Double.POSITIVE_INFINITY || bendra_suma2 == Double.NEGATIVE_INFINITY )
            MAPE = 0;
        else MAPE = bendra_suma2 / applet.testing_data_AR_Count;
        MAPE_test_value_AR_Label.setText( " = " + Double.toString( applet.round(MAPE, 3) ) );

        double PMAD = 0;
        if ( test_error_sum == Double.NaN || test_error_sum == Double.POSITIVE_INFINITY || test_error_sum == Double.NEGATIVE_INFINITY ||
            bendra_suma3 == Double.NaN || bendra_suma3 == Double.POSITIVE_INFINITY || bendra_suma3 == Double.NEGATIVE_INFINITY ||
            test_error_sum == 0 || bendra_suma3 == 0 )
                PMAD = 0;
        else PMAD = test_error_sum / bendra_suma3;
        PMAD_test_value_AR_Label.setText( " = " + Double.toString( applet.round(PMAD, 3) ) );

        double MSE = 0;
        if ( bendra_suma4 == Double.NaN || bendra_suma4 == Double.POSITIVE_INFINITY || bendra_suma4 == Double.NEGATIVE_INFINITY )
            MSE = 0;
        else MSE = bendra_suma4 / applet.testing_data_AR_Count;
        MSE_test_value_AR_Label.setText( " = " + Double.toString( applet.round(MSE, 3) ) );

        double RMSE = 0;
        if ( MSE == 0 ) RMSE = 0;
        else RMSE = Math.sqrt(MSE);
        RMSE_test_value_AR_Label.setText( " = " + Double.toString( applet.round(RMSE, 3) ) );

        double residual_variance = 0;
        residual_variance = ( bendra_suma4 - ((bendra_suma5*bendra_suma5)/applet.testing_data_AR_Count) ) / ( applet.testing_data_AR_Count - 1 );
        residual_variance_test_value_AR_Label.setText( " = " + Double.toString( applet.round(residual_variance, 3) ) );
    }
}