/*
 * RunId.java
 *
 * Created on 4 of February 2011, 15:49
 */

/**
 *
 * @author Eng. Paulo Roque Silva
 */
import java.util.Iterator;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ConcurrentLinkedQueue;

public class RunId implements Runnable {

    Neuron          []id;	                 // Neuron by TRAIL
    Neuron          []actNeuron;             // Neuron by TRAIL
    ConcurrentLinkedQueue<Signal> busIn;     // Queue in
    ConcurrentLinkedQueue<Signal> busOut;    // Queue Out
    ConcurrentLinkedQueue<Signal> bus;   	 // Queue In Past
    CyclicBarrier   bar;                     // Step barrier
    CyclicBarrier   bar2;                     // Step barrier
    Iterator<Signal> listen;                 // Listen id from busIn
    Signal			signInput;	 			 // Read input Signal
    boolean			isNext,					 // If is to be next
    				isProp;					 // If is the proprioceptin RunId
    int				next,                    // next to keep
    				nextAct,                 // next to keep
    				nNeurons;				 // # neurons
    int				i, j;                    // Indexes to For cycles
   
    /** Creates a new instance of RunId */
    public RunId(CyclicBarrier barr, CyclicBarrier barr2, Neuron []IdNeurons,
                             ConcurrentLinkedQueue<Signal> queueIn,
                             ConcurrentLinkedQueue<Signal> queueOut,
                             ConcurrentLinkedQueue<Signal> queue,
                             int nNodes) {
        
        bar        = barr;
        bar2       = barr2;
        id         = IdNeurons;
        busIn      = queueIn;
        busOut     = queueOut;
        bus	       = queue;
        next	   = 0;
        nextAct	   = 0;
        isProp	   = false;
        nNeurons   = nNodes;
    }
    
    /** Creates a new instance of RunId */
    public RunId(CyclicBarrier barr, CyclicBarrier barr2, Neuron []IdNeurons,
                             ConcurrentLinkedQueue<Signal> queueIn,
                             ConcurrentLinkedQueue<Signal> queueOut,
                             ConcurrentLinkedQueue<Signal> queue, Neuron[] actNode,
                             int nNodes) {
        
        bar        = barr;
        bar2       = barr2;
        id         = IdNeurons;
        busIn      = queueIn;
        busOut     = queueOut;
        bus	       = queue;
        next	   = 0;
        nextAct	   = 0;
        actNeuron  = actNode;
        isProp	   = true;
        nNeurons   = nNodes;
    }
    
    public void run() {
    	boolean    areData;      // If sense something
    	
        while (!id[0].end && !bar.isBroken() && !bar2.isBroken() && id[0].step < nNeurons) {
            try {
                bar.await(); 
            }
            catch (InterruptedException ex) { 
                return;
            }
            catch (BrokenBarrierException ex) { 
                return;
                }
            areData = false;
            listen = bus.iterator();
            while (listen.hasNext()) {        // read all the input bus
            	signInput = listen.next();
                if (signInput.actPower > Liberu.MinSense)
                    areData = true;
            }
            isNext = false;
            if (busIn.isEmpty() && areData /*!bus.isEmpty() || isNext*/) {
            	id[next].setKeep(true);
            	if (isProp/* && isNext*/) {
            		actNeuron[nextAct].setStandby(true);
                	if (nextAct < nNeurons - 1)
                		nextAct += 1;
            	}
                isNext = true;
        	}
        	// ******************************* STEP 2 *************************************
        	try {
                bar2.await(); 
            }
            catch (InterruptedException ex) { 
                return;
            }
            catch (BrokenBarrierException ex) { 
                return;
                }
        	while (!busOut.isEmpty())
        		busOut.poll();
        	listen = busIn.iterator();
            while (listen.hasNext()) {        // read all the input bus
            	signInput = listen.next();
            	busOut.add(new Signal(signInput.emitter, signInput.actPower));
            }
            if (isNext) {
        		id[next].setKeep(false);
            	if (next < nNeurons - 1) {
            		next += 1;
            		id[next].setStandby(true);
                	for (i=0; i<nNeurons; i++)
                		id[i].addStep();
                }
            }
    	} // End While
    }
}
