package main;

import Jama.Matrix;

public class ARMA_method {
    private double data[];
    //private double errors[];
    private double coef_b[];
    private int p;
    private int m;
    private int n;
    private double det;
    private double MA[];
    //private double MA_array[];
    private double A[][];
    private double B[][];
    private double X[];

    public ARMA_method( double[] v, int p, double[] MA_array, double[] coef_b2 ) {
        this.p = p;
        this.data = v;
        this.n = v.length;
        this.m = this.n - this.p;
        this.MA = MA_array;
        this.coef_b = coef_b2;
        //printData();
        //printErrors();
    }

    public void A_() {
        A = new double[p][p];
        for ( int i = 0; i < p; i++ ) {
            for ( int j = 0; j < p; j++ ) {
               for ( int k = data.length-1; k > data.length-1-m; k-- ) {
                   A[i][j] += data[k-j-1] * data[k-i-1];
                   //System.out.println("A["+i+"]["+j+"] += "+data[k-j-1]+" * "+data[k-i-1]);
               }
            }
        }
        //printA();
    }
    
    /*public double[] MA_() {
        MA = new double[data.length];
        for ( int i = 0; i < coef_b.length; i++ ) {
            MA[i] = 0;
        }
        for ( int i = coef_b.length; i < data.length; i++ ) {
            for ( int b = 0; b < coef_b.length; b++ ) {
                MA[i] += coef_b[b] * errors[i-1-b];
            }
        }
        //printMA();   
        return MA;
    }*/

    public void B_() {        
        B = new double[p][1];
        for ( int i = 0; i < p; i++ ) {
           for ( int j = data.length-1; j > data.length-1-m; j-- ) {
               //System.out.println("j-1 = " + (j-1));
               if ( (j-1) >= 0 ) {
                   if ( (j-i-2) >= 0 ) {
                       B[i][0] += (data[j]-MA[j-1]) * (data[j-i-1]-MA[j-i-2]);
                       //System.out.println("B[" + i + "][0] += (" + data[j] + " - " + MA[j-1] + ") * (" + data[j-i-1] + " - " + MA[j-i-2] + ")");
                   }
                   else {
                       B[i][0] += (data[j]-MA[j-1]) * data[j-i-1];
                       //System.out.println("B[" + i + "][0] += (" + data[j] + " - " + MA[j-1] + ") * " + data[j-i-1]);
                   }
                   //System.out.println("MA["+(j-1)+"] = " + MA[j-1]);
                   //System.out.println("B[" + i + "][0] += (" + data[j] + " - " + MA[j-1] + ") * (" + data[j-i-1] + ")");
               }
               else {
                   B[i][0] += data[j] * data[j-i-1];
                   //System.out.println( "B[" + i + "][0] += " + data[j] + " * " + data[j-i-1] );
               }
           }
        }
        //printB();
    }

    public double[] rezult() {
        A_();
        B_();
        Matrix A_matrix = new Matrix(A);
        det = A_matrix.det();
        Matrix b_matrix = new Matrix(B);
        while ( det < 0.050 ) {
            p = p - 1;
            A_();
            B_();
            A_matrix = new Matrix(A);
            det = A_matrix.det();
            b_matrix = new Matrix(B);
        }
        Matrix x_matrix = A_matrix.solve(b_matrix);
        double [][] temp = x_matrix.getArrayCopy();
        X = new double[p];
        for( int i = 0; i < temp.length; i++ )
            X[i] = temp[i][0];

        /*System.out.println( "matrica X ------------------------" );
        for ( int i = 0; i < X.length; i++ )
             System.out.println( X[i] );
        System.out.println( "matrica X ------------------------" );*/

        return X;
    }
    
    public void printB() {
        System.out.println( "matrica B start ------------------------" );
        for( int i = 0; i < B.length; i++ )
             System.out.println( B[i][0] );
        System.out.println( "matrica B end ------------------------" );
    }

     public void printA() {
        System.out.println( "matrica A start ------------------------" );
        String s;
        double temp2;
        for ( int i = 0; i < p; i++ ) {
            s = "";
            for ( int j = 0; j < p; j++ ) {
                temp2 = Math.round( A[i][j] * 100 );
                temp2 = temp2 / 100;
                s += temp2 + " ";
            }
            System.out.println( s );
        }
        System.out.println( "matrica A end ------------------------" );
     }

     private void printData() {
        System.out.println( "matrica DATA start ------------------------" );
        for( int i = 0; i < data.length; i++ )
             System.out.println( data[i] );
        System.out.println( "matrica DATA end ------------------------" );
    }
     
     /*private void printMA() {
        System.out.println( "matrica MA start ------------------------" );
        for( int i = 0; i < MA_array.length; i++ )
             System.out.println( MA_array[i] );
        System.out.println( "matrica MA end ------------------------" );
    }
     
     private void printErrors() {
        System.out.println( "matrica Errors start ------------------------" );
        for( int i = 0; i < errors.length; i++ )
             System.out.println( errors[i] );
        System.out.println( "matrica Errors end ------------------------" );
    }*/
}