// Liaison, herite de CircuitElement
public class Liaison extends CircuitElement {
	
	// Les pins de la liaison (pas d'ordre)
	private Pin pin_a;
	private Pin pin_b;
	
	// Constructeur avec les 2 pins a connecter
	public Liaison(Pin pin_a, Pin pin_b) throws Exception{ // Lance une exception si un des pins est incorrecte)
		// On initialise les pins
		setA(pin_a);
		setB(pin_b);
		// On initialise leurs valeurs
		if(pin_a.isOn() && !pin_b.isOut()) pin_b.setState(true);
		else if(pin_b.isOn() && !pin_a.isOut()) pin_a.setState(true);
	}
	
	// Destruction de la liaison
	public void Dispose(){
		if(isDisposed) return;
		super.Dispose();
		clearA();
		clearB();
		pin_Listener = null;
	}
	
	// Premier pin
	public Pin getA(){
		if(isDisposed) return null;
		return pin_a;
	}
	
	public void setA(Pin pin) throws Exception{
		if(isDisposed) return;
		if(pin == null) throw new Exception("Null Pin Exception"); // Si un pin est null, lancer une erreur
		if(pin_a == pin) return;
		clearA(); // Effacer l'ancien pin
		pin_a = pin;
		pin.addPinListener(pin_Listener); // Ecouter ses changements d'etats
	}
	
	private void clearA(){
		if(pin_a == null) return;
		pin_a.remPinListener(pin_Listener); // Arrete d'ecouter ses changements d'etats
		pin_a.askState(); // Comme il ne nous appartient plus, il doit essayer de retrouver la valeur qu'il est sense avoir
		pin_a = null;
	}
	
	// Idem pour le second pin
	public Pin getB(){
		if(isDisposed) return null;
		return pin_b;
	}
	
	public void setB(Pin pin) throws Exception{
		if(isDisposed) return;
		if(pin == null) throw new Exception("Null Pin Exception");
		if(pin_b == pin) return;
		clearB();
		pin_b = pin;
		pin.addPinListener(pin_Listener);
	}
	
	private void clearB(){
		if(pin_b == null) return;
		pin_b.remPinListener(pin_Listener);
		pin_b.askState();
		pin_b = null;
	}
	
	// Ecouteur des changements d'etats des pins
	Pin.PinListener pin_Listener = new Pin.PinListener() {
		public void stateChanged(Pin pin) {
			if(pin==null) return;
			if(pin == pin_a){ // Lorsqu'un pin change de valeur, on previent l'autre
				if(pin_b!=null && !pin_b.isOut()) pin_b.setState(pin_a.on);
			}else if(pin == pin_b){
				if(pin_a!=null && !pin_a.isOut()) pin_a.setState(pin_b.on);
			}
		}

		public void disposed(Pin pin) {
			Liaison.this.Dispose(); // Si on pin est detruit, on s'auto detruit
		}

		public boolean askState(Pin pin){ // Si un pin veut connaitre sa valeur, on essaye de la retrouver
			if(pin == null || isDisposed || pin.isDisposed())	return false;
			if(pin.isOut()) return false;
			if(!pin_a.isOut() && !pin_b.isOut()) return false;
			if(pin == pin_b && pin_a != null)		return pin_a.isOn();
			if(pin == pin_a && pin_b != null)		return pin_b.isOn();
			return false;
		}
	};
	
}
