import java.util.ArrayList;
import java.util.Collection;

// Pin
public class Pin {
	
	// Pin de sortie (pour eviter les liaisons entre 2 pins de sorties)
	private boolean isOut = false;
	public boolean isOut(){ return isOut; }
	
	// Nom du pin
	public String name = "Pin";

	// Valeur du pin
	boolean on = false;
	public boolean isOn(){ return on; }

	// Constructeur
	public Pin(){}
	public Pin(boolean isOut){
		this.isOut = isOut;
	}
	
	// Changer l'etat d'un pin
	public void setState(boolean on){
		if(isDisposed) return;
		if(this.on == on) return; // Si l'etat est deja celui voulu, on ne fait rien
		if(!isOut) this.on = false;
		if(on==false){
			on = fireAskState(); // Si on veut le mettre a "Off", il doit d'abord verifier qu'aucun autres liaisons dont il faut partie le bloque a "On"
		}
		this.on = on;
		fireStateChanged(); // On previent qu'on a changer peut etre d'etat
	}
	
	// Demander son etat
	public void askState(){
		setState(isOut?on:fireAskState());
	}
	
	// Gestion de la destruction du pin
	private boolean isDisposed = false;
	public boolean isDisposed(){ return isDisposed; }
	public void finalize(){ Dispose(); }
	public void Dispose(){
		if(isDisposed) return;
		isDisposed = true;
		if(on){
			on = false;
			fireStateChanged();
		}
		fireDisposed();
		pinListeners.clear();
		pinListeners = null;
	}
	
	// Ecouteur du pin (changement d'etat, demande d'etat, destruction)
	public interface PinListener {
	    void stateChanged(Pin pin);
	    boolean askState(Pin pin);
	    void disposed(Pin pin);
	}
	
	private Collection<PinListener> pinListeners = new ArrayList<PinListener>();
	public void addPinListener(PinListener listener) {
		if(isDisposed) return;
		pinListeners.add(listener);
    }    
    public void remPinListener(PinListener listener) {
    	if(isDisposed) return;
    	pinListeners.remove(listener);
    }
    
    private boolean fireAskState(){
    	for(PinListener pinListener : pinListeners){
    		if(pinListener.askState(this)) return true; // TODO crade interface/classe
    	}
    	return false;
    }
    private void fireStateChanged(){
    	for(PinListener pinListener : pinListeners)
    		pinListener.stateChanged(this);
    }
    private void fireDisposed(){
    	for(PinListener pinListener : pinListeners)
    		pinListener.disposed(this);
    }
}
