package sim.engine;

public class EnginePeer
{
	protected NodeList inputPins;
	protected NodeList outputPins;
	protected EngineModule parent;
	protected double wakeUpTime;
	
	public EnginePeer(int input, int output, EngineModule em)
	{
		this.inputPins = new NodeList(input);
		this.outputPins = new NodeList(output);
		
		this.parent = em;
		this.wakeUpTime = Double.POSITIVE_INFINITY;
	}
	
	public EnginePeer(int input, EngineModule em)
	{
		this.inputPins = new NodeList(input);
		this.outputPins = null;
		
		this.parent = em;
		this.wakeUpTime = Double.POSITIVE_INFINITY;
	}
	
	public EngineModule getParent()
	{
		return this.parent;
	}
	
	public void setInputPin(int index, Node node)
	{
		this.inputPins.changeItem(index, node);
		node.addComponent(this);
	}
	
	public void setOutputPin(int index, Node node)
	{
		this.outputPins.changeItem(index, node);
	}
	
	public void resetInputPin(int index)
	{
		this.inputPins.resetItem(index);
	}
	
	public void resetOutputPin(int index)
	{
		this.outputPins.resetItem(index);
	}
	
	public void simulateComponent(double currentTime) throws EngineException
	{
		Data[] currentInputs = new Data[this.inputPins.getSize()];
		
		for(int loopNumber = 0; loopNumber < this.inputPins.getSize(); loopNumber++)
			currentInputs[loopNumber] = this.inputPins.getItemAt(loopNumber).getHistory();
		
		this.parent.evaluateOutput(currentTime, currentInputs, this);
	}
	
	public double getWakeUp()
	{
		return this.wakeUpTime;
	}
	
	public void setWakeUp(double time)
	{
		this.wakeUpTime = time;
	}
	
	public void sleep()
	{
		this.wakeUpTime = Double.POSITIVE_INFINITY;
	}
	
/* ====================================
       Normal Transaction
   ====================================*/
	
	public void normalTransaction(int index, Signal newData)
	{
		this.outputPins.getItemAt(index).getFuture().sortedInsert(newData);
	}
	
	
/* ====================================
       Clear-Uncomplited Transaction
   ====================================*/
	
	public void clearUncomplitedTransaction(int index, Signal newData)
	{
		this.outputPins.getItemAt(index).getFuture().clearAfterInsert(newData);
	}
	
/* ====================================
       Clear-All Transaction
   ====================================*/
	
	public void setOutputPinValue(int index, boolean newValue, double time)
	{
		this.outputPins.getItemAt(index).getFuture().destructiveInsert(new Signal(newValue, time, false, this, index));
	}
	
	public void setOutputPinUndefined(int index, double time)
	{
		this.outputPins.getItemAt(index).getFuture().destructiveInsert(new Signal(false, time, true, this, index));
	}
	
	public void floatOutputPin(int index, double time)
	{
		this.outputPins.getItemAt(index).getFuture().destructiveInsert(new Signal(time, this, index));
	}
}