package main;

import lp.constant;
import lp.lprec;
import lp.solve;

public class LpSolveABS implements constant {
    public static int result;

    public LpSolveABS() {

    }

    public double[] predict ( double[] data, int p, double[] MA_array, double[] coef_b ) {
        
        /*System.out.println( "ARMAABS_data ------------------------" );
        for ( int i = 0; i < data.length; i++ )
             System.out.println( data[i] );
        System.out.println( "ARMAABS_data ------------------------" );
        
        System.out.println( "ARMAABS_MA_array ------------------------" );
        for ( int i = 0; i < MA_array.length; i++ )
             System.out.println( MA_array[i] );
        System.out.println( "ARMAABS_MA_array ------------------------" );*/
        
        /*System.out.println( "ARMAABS_coef_b ------------------------" );
        for ( int i = 0; i < coef_b.length; i++ )
             System.out.println( coef_b[i] );
        System.out.println( "ARMAABS_coef_b ------------------------" );*/
        
        double A = -0.01;
        int data_count = data.length;
        double[] new_data = new double[data_count+1];
        new_data[0] = 0;
        
        System.arraycopy(data, 0, new_data, 1, data_count);

        solve lpSolve = new solve();
        lprec lpIn = new lprec(0,(data_count+p*2));

        double minf[] = new double[data_count+p*2+1];
        double rib1[] = new double[data_count+p*2+1];
        double rib2[] = new double[data_count+p*2+1];

        for ( int i=1; i<=data_count; i++ ) {
            minf[i] = 1;
            lpSolve.set_lowbo(lpIn, i, A);
        }

        for ( int i=data_count+1; i<=data_count+p*2; i++ ) {
            minf[i] = 0;
            lpSolve.set_lowbo(lpIn, i, A);
        }

        lpSolve.set_obj_fn(lpIn, minf);
        lpSolve.set_minim(lpIn);

        for ( int i=1; i<=data_count; i++ ) {
            for ( int j=1; j<=data_count; j++ ) {
                if ( i == j ) {
                    rib1[j] = 1;
                    rib2[j] = -1;
                }
                else {
                    rib1[j] = 0;
                    rib2[j] = 0;
                }
            }
            int a = 1;
            for ( int j=1; j<=p; j++ ) {
                if ( i-j > 0 ) {
                    rib1[data_count+a] = new_data[i-j];
                    rib1[data_count+a+1] = -1*new_data[i-j];
                    
                    rib2[data_count+a] = new_data[i-j];
                    rib2[data_count+a+1] = -1*new_data[i-j];
                    
                    a = a + 2;
                }
            }
            
            /*double MA = 0;
            for ( int b = 0; b < coef_b.length; b++ ) {
                MA += coef_b[b] * errors[data.length-b-1];
                System.out.println("MA += " + coef_b[b] + " * " + errors[data.length-b-1]);
            }
            System.out.println("MA = " + MA);*/
            //System.out.println("i = " + i);
            lpSolve.add_constraint(lpIn, rib1, GE, new_data[i] + MA_array[i-1]);
            lpSolve.add_constraint(lpIn, rib2, LE, new_data[i] + MA_array[i-1]);
        }
        
        //lpSolve.print_lp(lpIn);

        try {
            result = lpSolve.solve(lpIn);
        }
        catch ( ArrayIndexOutOfBoundsException ex ) {
            System.out.println("Error2:" + ex);
            result = 1000000;
        }

        if ( result == constant.OPTIMAL ) {
            int rows = lpIn.getRows();

            for ( int i = 1; i <= data_count+p*2; i++ ) {
                minf[i] = lpIn.getBestSolution(rows+i);
            }
            
            double[] coef = new double[p];
            for ( int i = 0; i < p; i++ ) {
                coef[i] = minf[data_count+i+1] - minf[data_count+p+i+1];
            }
            return coef;
        }
        else {
            double[] coef = new double[0];
            //System.out.println("No optimal solution");
            return coef;
        }
    }
}