/*
 * Cerebellum.java
 *
 * Created on 27 of February 2013, 17:45
 */

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

public class Cerebellum implements Runnable {

	static final int ESCape = Brain.NEURONS + 100; // Mentor or Random
	Cortex          past; // all memory
	Neuron	        []neuroLeft; // Neuron
	Neuron	        []neuroRigth; // Neuron
    CyclicBarrier   bar; // Step barrier
    Iterator<Signal> listen; // Listen id from busIn
    Signal			signInput; // Read input Signal
    int				pointerSelf, // sync action hemispheres with Time
    				nNeurons,
    				inv; // inverts action
    
    public Cerebellum(CyclicBarrier barr, Neuron []he, Neuron []hd,
    		          Cortex p, int nNTime) {

    	bar       = barr;
    	neuroLeft = he;
    	neuroRigth= hd;
    	past      = p;
    	nNeurons  = nNTime;
	}

    public void writeBus(int time) {
    	int i, // index
    		absTime;
    	
        // Write BusOut
    	absTime = Math.abs(time);
    	if (absTime != ESCape && Emotions.IdAct1 == ESCape)
        	for (i=0; i<neuroLeft[absTime].perception.size(); i++) {
            	Brain.BusInAct.add(new Signal(inv * neuroLeft[absTime].getPerception(i).emitter,
            			(int)(neuroLeft[absTime].getPerception(i).actPower * Neuron.Habit),
            			neuroLeft[absTime].getPerception(i).pleasure));	// power + acceleration
            	System.out.println(neuroLeft[absTime].getPerception(i).actPower); // REMOVE
            }
    }
    
    public void run() {
    	boolean salta;
    	
    	while (!Neuron.end && !bar.isBroken()) {
    		try {
                bar.await(); 
            }
            catch (InterruptedException ex) { 
                return;
            }
            catch (BrokenBarrierException ex) { 
                return;
            }
            // Present neuron - see different process - Attention
    		pointerSelf = neuroLeft[0].pointer; // +1 offset because beginning???
//            if (neuroLeft[0].pointer >= nNeurons - 1)
//            	pointerSelf = 0;
            neuroLeft[pointerSelf].clearPerceptions();
            listen = Brain.BusInProSelf.iterator();
            while (listen.hasNext()) { // read all the input bus
               	signInput = listen.next();
               	neuroLeft[pointerSelf].addPerception(signInput.emitter,
               			signInput.actPower, signInput.pleasure);
        	}

            while (!Brain.BusInAct.isEmpty())
        		Brain.BusInAct.poll();
            //******************* in ****************
        	salta = false;
        	listen = Brain.BusInCerebellum.iterator();
        	while (listen.hasNext()) {
            	signInput = listen.next();
            	if (signInput.emitter == ESCape)
                	salta = true;
        	}
        	listen = Brain.BusInCerebellum.iterator();
        	if (listen.hasNext() && !salta) {
            	while (listen.hasNext()) {
                	signInput = listen.next();
            		inv = 1;
            		if (signInput.emitter < 0)
                		inv = -1;
                	writeBus(signInput.emitter);
            	}
        	}
        	else { // PARA - PARA - PARA, donīt execute writeBus()
        		if (!salta) {
            		inv = 1;
            		if (Emotions.Good < 0)
                		inv = -1;
                	writeBus(Emotions.Good); // DIRAC
        		}
        	}
        }  // End While
    }
}