// Composant logique, herite de CircuitElement, classe abstraite
public abstract class Composant extends CircuitElement {
	
	// Constructeur
	public Composant(){
		super();
	}
	
	// Constructeur en precisant le nombre de pins d'entrees et sorties
	public Composant(int n_in, int n_out){
		super();
		createPins(n_in, n_out);
		beginWork();
		doWork();
	}
	
	// Destruction du composant
	public void Dispose(){
		if(isDisposed) return;
		super.Dispose();
		endWork(); // Appel de la procedure de fin
		for(Pin pn : pin_in)
			pn.Dispose();
		// Suppression des pins
		pin_in.clear();
		pin_in = null;
		for(Pin pn : pin_out)
			pn.Dispose();
		pin_out.clear();
		pin_out = null;
		// Suppression de l'ecouteur
		pinListener = null;
	}
	
	// Creation des pins avec n_in entrees et n_out sorties
	protected void createPins(int n_in, int n_out){
		if(isDisposed) return;
		for(int i=0; i<n_in; i++){
			Pin p_in = new Pin();
			p_in.addPinListener(pinListener);
			p_in.name = "In "+(i+1); // On nomme les pins d'entrees "In X"
			pin_in.add(p_in);
		}
		for(int i=0; i<n_out; i++){
			Pin p_out = new Pin(true);
			p_out.addPinListener(pinOutListener);
			p_out.name = "Out "+(i+1); // "Out X" pour les pins de sorties
			pin_out.add(p_out);
		}
	}
	
	// Ecouteur de changement d'etat d'un des pins
	private Pin.PinListener pinListener = new Pin.PinListener() {
		public void stateChanged(Pin pin) { // Quand l'etat d'un pin change
			if(isDisposed) return;
			doWork(pin); // On rappelle la procedure du composant
		}

		public void disposed(Pin pin) {
			Composant.this.Dispose(); // Quand un se detruit, on detruit le composant
		}

		public boolean askState(Pin pin) {
			return false; // Quand un PIN demande son etat, il ne sait pas
		}
	};
	
	// Ecouteur des pins
	private Pin.PinListener pinOutListener = new Pin.PinListener() {
		public void stateChanged(Pin pin) {}

		public void disposed(Pin pin) {
			Composant.this.Dispose();
		}

		public boolean askState(Pin pin) {
			return false;
		}
	};
	
	protected void beginWork(){} // Procedure appeler a l'initialisation du composant
	protected void doWork(Pin pin){doWork();} // Procedure appeler lors d'un changement d'etat d'un pin (passe en parametre)
	protected void doWork(){} // Procedure appeler lors d'un changement d'etat (si on ne prend pas en compte tel ou tel pin)
	protected void endWork(){} // Procedure appeler pour finaliser un composant
	
}
