//Oblique_State.java
//import maestro.lib.math.*;
import java.util.*;

public class Oblique_State {
    public static final double epsilon0 = 8.841941286E-12; 
    public static final double mu0 = 1.25663706144E-6; //Units H/m
    //exact values
    //private static final double epsilon0 = 8.8541878176E-12; //Units: F/m
    //private static final double mu0 = 1.25663706144E-6; //Units H/m
    //private static final double c = 1.0/Math.sqrt(epsilon0*mu0); //Units m/s
    private static final double c = 3.0E8; //Units m/s
    
    public double epsilon_r1, mu_r1, conductivity1; //Units S/m
    public double epsilon_r2, mu_r2, conductivity2; //Units S/m
    public boolean isPolarizationParallel, Incident, Reflected, Total, Plot2D, IsScalePlot;
    double wavelength1, wavelength2;
    double wavelength1x, wavelength2x;
    double wavelength1z, wavelength2z;
    double phase_velocity1, phase_velocity2;
    double phase_velocity1x, phase_velocity2x;
    double phase_velocity1z, phase_velocity2z;
    double alpha1, alpha2, beta1, beta2, beta1_z, beta1_x, beta2_z, beta2_x, beta_ratio; //attentuation coefficient and wave vector
    double E0; //Amplitudes of E-Field
    double loss_tangent1, loss_tangent2;
    double skin_depth1, skin_depth2;
    public Complex wave_impedance1, wave_impedance2;
    public double ratioZ;
    public double Deltax = 0.01;
    public double wt, dwt;
    public int NSteps,  ShowWhich;
    
    public int width=603;
    public int height=603;
    
    //public int width=301;
    //public int height=301;
    
    public double myarray[][];
    public double xarrayInc_M[];
    public double xarrayRef_M[];
    public double xarrayTot_M[];
    public double xarrayTot_M2[];
        
    public Complex Reflection_Coef, Reflection_CoefH, Transmission_Coef, Transmission_CoefH;
    double wave_impedance_mag1, wave_impedance_phase1, wave_impedance_mag2, wave_impedance_phase2;
    public double theta1, theta2, theta1_deg;
    public double frequency, angular_frequency, total_angle, totalR_angle;
    public double x[], ref_array[], trans_array[], refCM_array[], transCM_array[],
                  refCR_array[], transCR_array[], refCI_array[], transCI_array[];
    public Complex refC_array[], transC_array[];
    public double x_deg[], x_swp[];
    
    public int which = 1;
    public boolean plotE;
    public boolean IsVectorIn = true;
    public boolean show_normal = true;
    public boolean show_tang = true;
    
    public int Nt = 6000;
    private double PI = Math.PI;
    public int palettereference = 382;
    public int palettereferenceB = 127;
    public int palettereferenceC = 127;
    public boolean IsThreshold = false;
    public boolean IsCoarser = true;
    
    public boolean LicenseExpired;
    public int this_month, today_week, this_year, this_hour, this_minute, today_month, 
	       today_year,this_zone, saving_time;       
    GregorianCalendar Greg = new GregorianCalendar();
    
    public Oblique_State(){   
        
        NSteps = 180;//Change this to vary animation speed
	wt = 0.0;
	dwt = Math.PI*2/(NSteps);
	
	theta1 = 0.0; //Math.PI*0.25;
        theta1_deg = 0.0; //45;
	theta2 = Math.PI/4.0;
	epsilon_r1 = 1.0;
	mu_r1 = 1.0;
	conductivity1 = 0.0;
	epsilon_r2 = 2.55;
	mu_r2 = 1.0;
	conductivity2 = 0.0;
	isPolarizationParallel = true;
	frequency = 1.0E9;
	
        Incident = true;
        Reflected = false;
        Total = false;
        Plot2D = false;
        IsScalePlot = false;
        plotE = true;
        
        ShowWhich = 1;
        
        myarray = new double[width+1][height+1];
        xarrayInc_M = new double[height+1];
        xarrayRef_M = new double[height+1];
        xarrayTot_M = new double[height+1];
        xarrayTot_M2 = new double[height+1];
        
        x_swp = new double[height+1];
       
	this_month = Greg.get(Calendar.MONTH);
	//System.out.println("  This is the month = "+this_month);
	today_week = Greg.get(Calendar.DAY_OF_WEEK);
	//System.out.println("  This is the day_week = "+today_week);
	this_year = Greg.get(Calendar.YEAR);
	this_hour = Greg.get(Calendar.HOUR_OF_DAY);
	//System.out.println("  This is the year = "+this_year);
	this_minute = Greg.get(Calendar.MINUTE);
	//System.out.println("  This is the minute = "+this_minute);
	today_month = Greg.get(Calendar.DAY_OF_MONTH);
	//System.out.println("  This is the day_month = "+today_month);
	today_year = Greg.get(Calendar.DAY_OF_YEAR);
	//System.out.println("  This is the day_year = "+today_year);
	this_zone = Greg.get(Calendar.ZONE_OFFSET);
	//System.out.println("  This is the zone_offset = "+this_zone/3600000);
	saving_time = Greg.get(Calendar.DST_OFFSET);
	//System.out.println("  This is the dst_offset = "+saving_time/3600000);

	ignition();
	scan_coefficients();
    }
    
    public synchronized void increment(){
	wt+=dwt;
	if(wt > Math.PI * 2){
		wt -= 2 * Math.PI;
	}
        //System.out.println(wt);
    }
    
    public void ignition(){
        
        angular_frequency = 2.0 * Math.PI * frequency; // rad/s
	theta1_deg = MaestroA.rounder(theta1*180.0/Math.PI,4);
        
	beta1  = EMF.getBeta(epsilon_r1,mu_r1,conductivity1,angular_frequency);
	beta2  = EMF.getBeta(epsilon_r2,mu_r2,conductivity2,angular_frequency);
	beta_ratio = beta2/beta1;
        beta1_z = beta1 * Math.sin(theta1);
        beta1_x = Math.sqrt(beta1*beta1 - beta1_z*beta1_z);
        
        alpha1 = EMF.getAlpha(epsilon_r1,mu_r1,conductivity1,angular_frequency);
	alpha2 = EMF.getAlpha(epsilon_r2,mu_r2,conductivity2,angular_frequency);
	
	wavelength1 = EMF.getWaveLength(epsilon_r1,mu_r1,conductivity1,angular_frequency);
	wavelength2 = EMF.getWaveLength(epsilon_r2,mu_r2,conductivity2,angular_frequency);
        wavelength1z = wavelength1/Math.sin(theta1);
        wavelength2z = wavelength2/Math.sin(theta2);
	wavelength1x = wavelength1/Math.cos(theta1);
        wavelength2x = wavelength2/Math.cos(theta2);
        
	phase_velocity1 = EMF.getPhaseVelocity(epsilon_r1,mu_r1,conductivity1,angular_frequency);
	phase_velocity2 = EMF.getPhaseVelocity(epsilon_r2,mu_r2,conductivity2,angular_frequency);
	
        phase_velocity1z = phase_velocity1/Math.sin(theta1);
	phase_velocity2z = phase_velocity2/Math.sin(theta2);
	
        phase_velocity1x = phase_velocity1/Math.cos(theta1);
	phase_velocity2x = phase_velocity2/Math.cos(theta2);
        
	wave_impedance1 = EMF.getWaveImpedance(epsilon_r1,mu_r1,conductivity1,angular_frequency);
	wave_impedance2 = EMF.getWaveImpedance(epsilon_r2,mu_r2,conductivity2,angular_frequency);
				
        ratioZ = Complex.Real(Complex.Divide(wave_impedance1,wave_impedance2));
        
	theta2 = Math.asin(beta1*Math.sin(theta1)/beta2);//Snell's law
	
        beta2_z = beta1 * Math.sin(theta1);
        beta2_x = Math.sqrt(Math.abs(beta2*beta2 - beta2_z*beta2_z));
        
	/*
        Reflection_Coef =  EMF.getOblique_Reflection_Coefficient(theta1, epsilon_r1, epsilon_r2,
	    mu_r1, mu_r2, conductivity1, conductivity2, angular_frequency, isPolarizationParallel);
	    
        Reflection_CoefH = Complex.Multiply(Reflection_Coef,new Complex(-1.0,0.0));
        
	Transmission_Coef = EMF.getOblique_Transmission_Coefficient(theta1, epsilon_r1, epsilon_r2,
	    mu_r1, mu_r2, conductivity1, conductivity2, angular_frequency, isPolarizationParallel);
	
        Transmission_CoefH = Complex.Multiply(ratioZ,Transmission_Coef);
        */
        
        Reflection_Coef =  new Complex(-1.0,0.0);
	    
        Reflection_CoefH = new Complex(1.0,0.0);
        
	Transmission_Coef = new Complex(0.0,0.0);
	
        Transmission_CoefH = new Complex(0.0,0.0);
        
        
        total_angle = MaestroA.rounder(180.0/Math.PI*Math.atan(Math.sqrt((mu_r2*epsilon_r2)/(mu_r1*epsilon_r1))),4);
        //if((mu_r1*epsilon_r1) <= (mu_r2*epsilon_r2) ){
        //    totalR_angle = 91.0;
        //}
        //else
        {
            totalR_angle = MaestroA.rounder(180.0/Math.PI*Math.asin(Math.sqrt((mu_r2*epsilon_r2)/(mu_r1*epsilon_r1))),4);
        }
        
            int mid = 3*width/4;
            int mid2 = 3*width/4;
            Complex useT, useR;
            
            if(isPolarizationParallel){
                useR = Reflection_CoefH;
                useT = Transmission_CoefH;
            }
            else{
                useR = Reflection_Coef;
                useT = Transmission_Coef;
            }
            
            if(Plot2D){
                if(Incident){
                    if(useT.Imaginary() == 0.0){
                        for(int j = 0; j < width+1; j++){
                            for(int i = 0; i < mid+1; i++){
                                myarray[j][i] = 
                                    300.0*Math.cos(wt - beta1_x/beta1*(double)(i-mid)*Deltax + beta1_z/beta1*(double)(j-mid2)*Deltax);
                            }
                            for(int i = mid+1; i < height+1; i++){
                                myarray[j][i] = 300.0*useT.Real()*Math.cos(wt - beta2_x/beta1*(double)(i-mid)*Deltax + beta2_z/beta1*(double)(j-mid2)*Deltax);
                            }
                        }
                    }
                    else{
                        for(int j = 0; j < width+1; j++){
                            for(int i = 0; i < mid+1; i++){
                                myarray[j][i] = 
                                    300.0*Math.cos(wt - beta1_x/beta1*(double)(i-mid)*Deltax + beta1_z/beta1*(double)(j-mid2)*Deltax);
                            }
                            for(int i = mid+1; i < height+1; i++){    
                                    myarray[j][i] = 300.0*useT.Magnitude()
                                                    * Math.exp(-Math.abs(beta2_x/beta1)*(double)(i-mid)*Deltax)
                                                    * Math.cos(wt + beta1_z/beta1*(double)(j-mid2)*Deltax + useT.Arg2());
                            }   
                        }
                    }
                }// end of if(Incident)
                //--------------------------------------------------------------
                if(Reflected){
                    if(useT.Imaginary() == 0.0){
                        for(int j = 0; j < width+1; j++){
                            for(int i = 0; i < mid+1; i++){
                                myarray[j][i] = 300.0*useR.Real()*Math.cos(wt + beta1_x/beta1*(double)(i-mid)*Deltax + beta1_z/beta1*(double)(j-mid2)*Deltax);
                            }
                            for(int i = mid+1; i < height+1; i++){
                                 myarray[j][i] = 300.0*useT.Real()*
                                    Math.cos(wt - beta2_x/beta1*(double)(i-mid)*Deltax + beta2_z/beta1*(double)(j-mid2)*Deltax);
                            }
                        }
                    }
                    else{
                        for(int j = 0; j < width+1; j++){
                            for(int i = 0; i < mid+1; i++){
                                myarray[j][i] = 300.0*useR.Magnitude()*Math.cos(wt + beta1_x/beta1*(double)(i-mid)*Deltax + beta1_z/beta1*(double)(j-mid2)*Deltax+useR.Arg2());
                            }
                            for(int i = mid+1; i < height+1; i++){    
                                myarray[j][i] = 300.0*useT.Magnitude() 
                                                * Math.exp(-Math.abs(beta2_x/beta1)*(double)(i-mid)*Deltax)
                                                * Math.cos(wt + beta1_z/beta1*(double)(j-mid2)*Deltax + useT.Arg2());
                            }
                        }
                    }
                }// end of if(Reflected)
                //--------------------------------------------------------------
                if(Total){
                    
                    if(useT.Imaginary() == 0.0){
                        for(int j = 0; j < width+1; j++){
                            for(int i = 0; i < mid+1; i++){
                                myarray[j][i] = 
                                300.0*Math.cos(wt - beta1_x/beta1*(double)(i-mid)*Deltax + beta1_z/beta1*(double)(j-mid2)*Deltax)+
                                300.0*useR.Magnitude()*Math.cos(wt + beta1_x/beta1*(double)(i-mid)*Deltax + beta1_z/beta1*(double)(j-mid2)*Deltax+useR.Arg2());
                            }
                            for(int i = mid+1; i < height+1; i++){
                                myarray[j][i] = 300.0*useT.Real()*
                                                  Math.cos(wt - beta2_x/beta1*(double)(i-mid)*Deltax + beta2_z/beta1*(double)(j-mid2)*Deltax);
                            }
                        }
                    }
                    else{
                        for(int j = 0; j < width+1; j++){
                            for(int i = 0; i < mid+1; i++){
                                myarray[j][i] = 
                                300.0*Math.cos(wt - beta1_x/beta1*(double)(i-mid)*Deltax + beta1_z/beta1*(double)(j-mid2)*Deltax)+
                                300.0*useR.Magnitude()*Math.cos(wt + beta1_x/beta1*(double)(i-mid)*Deltax + beta1_z/beta1*(double)(j-mid2)*Deltax+useR.Arg2());
                                //300.0*useR.Real()*Math.cos(wt + beta1_x/beta1*(double)(i-mid)*Deltax - beta1_z/beta1*(double)(j)*Deltax);
                            }
                            for(int i = mid+1; i < height+1; i++){    
                                myarray[j][i] = 300.0*useT.Magnitude() 
                                           * Math.exp(-Math.abs(beta2_x/beta1)*(double)(i-mid)*Deltax)
                                            * Math.cos(wt + beta1_z/beta1*(double)(j-mid2)*Deltax + useT.Arg2());
                            }
                        }
                    }
                }//end of if(Total)
                //--------------------------------------------------------------
                
                /*
                for(int j = 0; j < width+1; j++){
                            for(int i = 0; i < height+1; i++){
                                myarray[j][i] = Math.abs(myarray[j][i]); 
                            }
                }
                */
                
                
            }// end of if(Plot2D)
                
                if(theta1 == 0.0){
                    useR = Reflection_Coef;
                    Complex useR2 = Reflection_CoefH;
                    
                    for(int i = 0; i < mid+1; i++){
                        xarrayTot_M[i] = Complex.Magnitude(
                            Complex.Add(
                            new Complex(Math.cos(beta1_x/beta1*(double)(i-mid)*Deltax), Math.sin(beta1_x/beta1*(double)(i-mid)*Deltax)),
                            new Complex(useR.Magnitude()*Math.cos(beta1_x/beta1*(double)(i-mid)*Deltax+useR.Arg2()), 
                            -useR.Magnitude()*Math.sin(beta1_x/beta1*(double)(i-mid)*Deltax+useR.Arg2())))
                        );
                        xarrayTot_M2[i] = 0.75*Complex.Magnitude(
                      Complex.Add(
                            new Complex(Math.cos(beta1_x/beta1*(double)(i-mid)*Deltax), Math.sin(beta1_x/beta1*(double)(i-mid)*Deltax)),
                            new Complex(-useR.Magnitude()*Math.cos(beta1_x/beta1*(double)(i-mid)*Deltax+useR.Arg2()), 
                            useR.Magnitude()*Math.sin(beta1_x/beta1*(double)(i-mid)*Deltax+useR.Arg2())))
                        );
                    }
                }
                else{
                    for(int i = 0; i < mid+1; i++){
                        xarrayTot_M[i] = Complex.Magnitude(
                            Complex.Add(
                            new Complex(Math.cos(beta1_x/beta1*(double)(i-mid)*Deltax), Math.sin(beta1_x/beta1*(double)(i-mid)*Deltax)),
                            new Complex(useR.Magnitude()*Math.cos(beta1_x/beta1*(double)(i-mid)*Deltax+useR.Arg2()), 
                            -useR.Magnitude()*Math.sin(beta1_x/beta1*(double)(i-mid)*Deltax+useR.Arg2())))
                        );
                        xarrayTot_M2[i] = 0.0;
                    }
                }
                for(int i = mid+1; i < height+1; i++){
                        //xarrayTot_M[i] = useT.Magnitude()*Math.exp(-Math.abs(beta2_x/beta1)*(double)(i-mid)*Deltax);
                            xarrayTot_M[i] = 0.0;
                }
                    
                
                //--------------------------------------------------------------
                for(int i = 0; i < height+1; i++){
                         x_swp[i] = i;
                         
                         //System.out.println(i+"   "+xarrayTot_M[i]);
                }
                //--------------------------------------------------------------
    }
    
    public void scan_coefficients(){
	x = new double[9001];
	x_deg = new double[9001];
	ref_array = new double[9001];
	trans_array = new double[9001];
	refC_array = new Complex[9001];
	transC_array = new Complex[9001];
        refCM_array = new double[9001];
	transCM_array = new double[9001];
	refCR_array = new double[9001];
	transCR_array = new double[90001];
        refCI_array = new double[9001];
	transCI_array = new double[9001];
	
        for(int i=0;i<9001;i++){
	    x_deg[i] = (double)i;
	}
	
        EMF.getOblique_Reflection_Coefficient(epsilon_r1, epsilon_r2, mu_r1, mu_r2, conductivity1, conductivity2,
				      angular_frequency, isPolarizationParallel, ref_array,x);
	EMF.getOblique_Transmission_Coefficient(epsilon_r1, epsilon_r2, mu_r1, mu_r2, conductivity1, conductivity2,
				      angular_frequency, isPolarizationParallel, trans_array,x);
                                      
        EMF.getOblique_Reflection_CoefficientC(epsilon_r1, epsilon_r2, mu_r1, mu_r2, conductivity1, conductivity2,
				      angular_frequency, isPolarizationParallel, refC_array,x);
	
        
        EMF.getOblique_Transmission_CoefficientC(epsilon_r1, epsilon_r2, mu_r1, mu_r2, conductivity1, conductivity2,
				      angular_frequency, isPolarizationParallel, transC_array,x);
        
        double ratio;
        ratio = Math.sqrt((mu_r1*epsilon_r2)/(mu_r2*epsilon_r1));
        
        
        if(plotE){}
        else{
            if(wavelength1 != wavelength2){
                for(int i=0;i<9001;i++){
                    refC_array[i] = Complex.Multiply(refC_array[i], new Complex(-1.0,0.0));
                    transC_array[i] = Complex.Multiply(transC_array[i], new Complex(ratio,0.0));
                }
            }
        }
        
        for(int i=0;i<9001;i++){
            refCR_array[i] = Complex.Real(refC_array[i]);
            transCR_array[i] = Complex.Real(transC_array[i]);
            refCI_array[i] = Complex.Imaginary(refC_array[i]);
            transCI_array[i] = Complex.Imaginary(transC_array[i]);
	    refCM_array[i] = Complex.Magnitude(refC_array[i]);
            transCM_array[i] = Complex.Magnitude(transC_array[i]);
            //System.out.println(i+"  "+refCR_array[i]+"   "+refCI_array[i]);
        }
        
    }
    
   
}