package main;

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

public class MyLp implements constant {
    public static int result;

    public MyLp() {

    }

    public double[] predict ( double[] data, int p ) {
        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);
        }
        
        /*System.out.println("minf ------------------------");
        for (int n = 0; n < minf.length; n++) {
            System.out.println(minf[n]);
        }
        System.out.println("minf ------------------------");*/

        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;
                }
            }
            lpSolve.add_constraint(lpIn, rib1, GE, new_data[i]);
            lpSolve.add_constraint(lpIn, rib2, LE, new_data[i]);
        }
        
        //lpSolve.print_lp(lpIn);
        //lpSolve.print_solution(lpIn);
        
        //System.out.println("rows = " + lpIn.getRows());
        //System.out.println("columns = " + lpIn.getColumns());
        
        /*System.out.println("rib1 ------------------------");
        for (int n = 0; n < rib1.length; n++) {
            System.out.println(rib1[n]);
        }
        System.out.println("rib1 ------------------------");*/
        
        /*System.out.println("rib2 ------------------------");
        for (int n = 0; n < rib2.length; n++) {
            System.out.println(rib2[n]);
        }
        System.out.println("rib2 ------------------------");*/

        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;
        }
    }
}