package physics;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JTextField;

import math.Maths;
import math.equation.RationalPolynomial;
import math.equation.RationalPolynomialComplex;
import math.matrix.Matrix;
import math.matrix.Vector;
import stdlib.StdDraw;
import awt.Draw;

/**
 * @author Daniel Weschke
 */
public class Nyquist{
	Draw nyquist = new Draw();
	static JTextField tf = new JTextField();
	static Thread plot;
	static Vector X;
	static Vector Y;
	
	public Matrix getNyquist() {
		RationalPolynomial PT11 = new RationalPolynomial("2; 4 1");
		RationalPolynomial PT12 = new RationalPolynomial("1; 6 1");
//		RationalFunction I = new RationalFunction("5; 24 0");
		RationalPolynomial sys = PT11.times(PT12).times(PT12).times(PT12);
		tf.setText(sys.a.toStr()+"; "+sys.b.toStr());
		RationalPolynomialComplex crf = new RationalPolynomialComplex(sys);
//		doule v = crf.getDivident().getRe().getCoef(0);
		PT11.setSymbolic("s");
		PT12.setSymbolic("s");
		sys.setSymbolic("s");
		crf.setSymbolic("s");
		return getNyquist(crf);
	}
	
	public Matrix getNyquist(RationalPolynomial sys) {
		tf.setText(sys.a.toStr()+"; "+sys.b.toStr());
		RationalPolynomialComplex crf = new RationalPolynomialComplex(sys);
		return getNyquist(crf);
	}
	
	public Matrix getNyquist(RationalPolynomialComplex crf){
		ArrayList<Double> X = new ArrayList<Double>();
		ArrayList<Double> Y = new ArrayList<Double>();
    	double omega, abs, angle;
    	double x=0, y=0, t=0;
		double epsilon = 1;
		double directionX, directionY;
		while(epsilon > 0.01){
			omega = t;
	    	abs = crf.mod(omega);
	    	angle = crf.argd(omega);
	    	directionX =  + abs * Maths.cosd(angle) - x;
	    	directionY =  - abs * Maths.sind(angle) - y;
	    	
			// Determine the pointers location
			x += directionX;
			y += directionY;
			t += 0.001;
			
			X.add(x);
			Y.add(y);
	    	epsilon = Maths.hypot(x, y);
		}
		
		// get array 
		Object xa[] = X.toArray();
		Object ya[] = Y.toArray();
		int imax = xa.length;
		double[] xd = new double[imax];
		double[] yd = new double[imax];
		// the array 
		for(int i=0; i<imax; i++){
			xd[i] = ((Double) xa[i]).doubleValue();
			yd[i] = -((Double) ya[i]).doubleValue();
		}
		return new Matrix(xd, yd);
	}
	
	public void setNyquist(){
		X = new Nyquist().getNyquist().getN(0);
		Y = new Nyquist().getNyquist().getN(1);
		nyquist = new Draw(X,Y);
	}
	
	public void setNyquist(RationalPolynomial sys){
		X = new Nyquist().getNyquist(sys).getN(0);
		Y = new Nyquist().getNyquist(sys).getN(1);
		nyquist = new Draw(X,Y);
	}
	
	public void demo(){
		setNyquist();
		contents();
		animate();
        nyquist.circle(0, 0, 1);
//        textLeft(nyquist.scaleRight/2, nyquist.scaleTop-0.1*v, String.format("|G| = %.1f", abs1));
//        textLeft(right/2, up-0.2*v, String.format(" \u03C9\u2081 = %.3f", omega1));
//        textLeft(right/2, up-0.3*v, String.format(" φr = %.1f°", angle1+180));
//        textLeft(right/2, up-0.4*v, String.format(" Ar = %.3f", 1/ar1));
//    	double x0 = abs1*(1-dl) * WMath.cosd(angle1);
//    	double y0 = abs1*(1-dl) * WMath.sind(angle1);
//    	double x1 = abs1*(1+dl) * WMath.cosd(angle1);
//    	double y1 = abs1*(1+dl) * WMath.sind(angle1);
//        line(ar1, -dl, ar1, dl);
//        text(ar1, v/25, "Ar\u207B\u00B9");
//        line(x0, y0, x1, y1);
//        text((abs1+dt*1.5)*WMath.cosd(angle1), (abs1+dt)*WMath.sind(angle1), "φr");
	}
	
	public void contents(){
		StdDraw.frame.setTitle("Nyquist");
		nyquist.setScale(-1.5,  2.5,  -2.5,  1.5);
		StdDraw.top = 20;
		StdDraw.frame.add(tf);
		tf.setBounds(0, 0, 512, 20);
		tf.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				nyquist.stop(); // ohne diesem bleiben noch einige punkte -> doppel thead?
				Draw.clear();
				nyquist.show(1);
				Draw.setProcess(0);
				RationalPolynomial sys = new RationalPolynomial(tf.getText().toString());
				setNyquist(sys);
				animate();
			}
		});
	}
	
	public void animate(){
		if(X==null) demo();
		nyquist.markX(-1);
		nyquist.animate();
	}
	
	/**
	 * 2.0 ; 264.0 348.0 80.0 22.0 1.0 
	 * 10.0 2.0 1.0 ; 864.0 648.0 180.0 22.0 
	 * 2.0 ; 64.0 1.0 1.0 
	 * @param args
	 */
	public static void main(String[] args) {
		Nyquist ny = new Nyquist();
//		ny.setNyquist(new RationalPolynomial("10.0 2.0 1.0 ; 864.0 648.0 180.0 22.0"));
//		ny.setNyquist(new RationalPolynomial("10.0 2.0 1.0 ; 864.0 648.0 180.0 22.0"));
		ny.animate();
		ny.nyquist.cross();
		System.out.println();
	}
}
