import java.awt.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.imageio.*;
import java.io.*;
import java.awt.image.*;
import java.net.*;

/**
 * Esta clase implementa el control <b>PID</b> del estanque
 * @author Francisco Cabezas
 * @author Manuel Gallardo
 */
public class Controller extends Equipment{

	public Controller (Point _position, Tank _t){
		t = _t;
		I_t=0;
		h_ref = Tank.H/2;
		k_I = 0.85F;
		k_P = 0.85F;
		position=_position;
		try {
//		
                    //File sourceimage = new File("controller.png");  // As applicatios, this is OK.
			URL url = getClass().getResource("controller.png");  //it works for applications and applets.
			controller = ImageIO.read(url);
		} catch (IOException e) {
	    }
		gui=new Box(BoxLayout.Y_AXIS); //Se cambia el eje X por el eje Y, para que se vea vertical
                JLabel nombre=new JLabel("Parametros del controlador PID");
                gui.add(nombre);
		JLabel label= new JLabel(" H_ref ");
		gui.add(label);
		SpinnerNumberModel levelSpinner= new SpinnerNumberModel(h_ref, 0.0, (float)Tank.H, 1);
		levelSpinner.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent e){
				SpinnerNumberModel sn=(SpinnerNumberModel)e.getSource();
				h_ref=sn.getNumber().floatValue();
			}
		});
		JSpinner spinner = new JSpinner(levelSpinner);
		label.setLabelFor(spinner);
		gui.add(spinner);
		label= new JLabel(" K Prop. ");
		gui.add(label);
		levelSpinner= new SpinnerNumberModel(k_P, 0.0, 3.0, 0.05);
		levelSpinner.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent e){
				SpinnerNumberModel sn=(SpinnerNumberModel)e.getSource();
				k_P=sn.getNumber().floatValue();
			}
		});
		spinner = new JSpinner(levelSpinner);
		gui.add(spinner);
		label= new JLabel(" K Integ. ");
		gui.add(label);
		levelSpinner= new SpinnerNumberModel(k_I, 0.0, 3.0, 0.05);
		levelSpinner.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent e){
				SpinnerNumberModel sn=(SpinnerNumberModel)e.getSource();
				k_I=sn.getNumber().floatValue();
			}
		});
		spinner = new JSpinner(levelSpinner);
		gui.add(spinner);
	}
	public void timeTick(float dt){
		float x, e_t, I_prev=I_t;
		e_t = h_ref-t.getLevel();
		I_t += k_I * e_t * dt;
		x = k_P * e_t + I_t;
		x*=(-1);
		x += 0.5;
		if (x>1) {
			x=1;
			I_t = I_prev; // do not integrate more when actuation is maximum.
		}                 // In control, this is referred to as without wind-up.
		if (x<0){
			x=0;
			I_t = I_prev; // do not integrate more when actuation is maximum.
		}                 // In control, this is referred to as without wind-up.
		t.setOutValve(x);
	}
	public void paint(Graphics2D g2d){
		g2d.drawImage(controller, null, position.x, position.y);
	}
	public Box getGUI(){
		return gui;
	}
        public float getRef(){
            return h_ref;
        }

private Tank t;
private BufferedImage controller;
private Point position;
private float k_I, k_P, h_ref, I_t; 
private Box gui;
}
