/*
 * Emotions.java
 *
 * Created on 21 of January 2010, 16:42
 */

/**
 *
 * @author Paulo Roque Silva
 */

import java.util.Iterator;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import icommand.nxt.Sound;
import javax.swing.*;
import javax.swing.event.*;

public class Emotions implements Runnable {
	static final int 				ActRandom 	= 30;
	// N�mero de passos aleat�rios
	static final int 				SpeakRandom = 15;
	// N�mero de vogais aleat�rias
	static final int 				NSpeaks = 3;
	// N�mero de Vogais
	static int						Normal = 0;
	private static final short[] 	noteNew     = {5, 40};
	private static final short[]	noteDor     = {2349,
													40};
	private static final short[]	noteRir     = {500,
													40};
	private static final short[]	noteChorar  = {100,
													40};
    public static int				QF, // Qualidade final
    								QP,
    								// Qualidade presente
    								QR,
    								// Qualidade lembrada
    								Good,
    								Good2,
    							// Identifica��o recordado
    								IdAct1, // A��o
    								idSound,
    								PwEm; // Amplitude a��o
    public static boolean			EmotionNew, // 
    								// Se novidade
    								ActualPain;
    								// Se sente Dor
    public static Signal 	        []BodyAct;
    							// A��es no corpo do rob�
    private Cortex					past; // Rede do c�rtex
    Iterator<Signal> 				listen; // Ouve bus
    CyclicBarrier 				    stepBarrDecision;
    							// Barreira do Emotions
    CyclicBarrier 				    stepBarrDecision2;
    							// Barreira 2 do Emotions
    public static boolean			emotional,
    								rir,
    								choro;
    							// Se fica emocional
    JTextField      				text; // Texto lido
    DocumentListener				listener; // Ouve bus
    String		  					key; // Tecla primida
    
    public Emotions(CyclicBarrier barrD,
    		CyclicBarrier barrD2, Cortex me,
    		Signal []bodyA, JTextField txt) {

    	stepBarrDecision = barrD;
    	stepBarrDecision2 = barrD2;
    	past 		 = me;
    	BodyAct 	 = bodyA;
	    text		 = txt;
    	PwEm 		 = Mind.Power;
	    emotional 	 = false;
	    rir			 = false;
	    choro		 = false;
    	ActualPain   = false;
    	IdAct1 		 = Cerebellum.ESCape; // Sem a��o
		idSound 	 = Cerebellum.ESCape;
        Liberu.Already = true;
        key = " ";
	    listener     = new LearnListener();
        text.getDocument().addDocumentListener(listener);
    }
    
    public void idAct1Action(int idAction) {
    	
		IdAct1 = idAction;
    }
	
    private static void express(short[] note) {
    	int i;
		
    	if (Liberu.Robot == 2)
        	for (i = 0; i < note.length; i += 2) {
        		final short w = note[i + 1];
        		final int n = note[i];
        		Sound.playTone(n, w * 10);
        	}
    	if (Liberu.Robot == 1)
    		try {
                Liberu.output.write((byte)110);
                Liberu.output.write('\n');
    		}
        	catch (Exception e) {
                System.err.println(e.toString());
        	}
    }
	
	public void emotionSpeak() {
		short []happySound = {1963, 80};

		if (Liberu.Robot == 1 || Liberu.Robot == 2) {
        	happySound[0] = (short)QF;
        	if (happySound[0] > 3000)
        		happySound[0] = 3000;
        	express(happySound);			//NXT
    	}
    	if (Liberu.Robot == 0) {
    		idSound = Cerebellum.ESCape;
        	if (IdAct1 == Cerebellum.ESCape) {
        		idSound = Brain.Vogal1 +
               			(int)Math.rint(Math.random() *
               			(Emotions.NSpeaks - 1));
               	BodyAct[idSound].setActive(true);
        		BodyAct[idSound].setActPower(PwEm);
        	}
    	}
    	System.out.println("SPEEK...  :-)"); //REMOVER
	}
	
	public void emotionNew(boolean empty) {

		// Emo��o de novidade - Genetica
		if (empty) {
			emotional = true;
			EmotionNew = true;
	    	if (Liberu.Robot == 2)
	    		express(noteNew); // comando NXT
	    	if (Liberu.Robot == 1)
				try {
		            Liberu.output.write((byte)106);
		            Liberu.output.write('\n');
				}
		    	catch (Exception e) {
		            System.err.println(e.toString());
		    	}
			System.out.println(
					"Emotion NEW...    :-0"); //REMOVER
			BodyAct[Brain.New].setActive(true);
		}
	}
	
	private void emotionNormal() {

		emotional = false;
    	ActualPain = false;
		EmotionNew = false;
		rir			= false;
		choro		= false;
		System.out.println(
				"Emotion Normal... :-|"); //REMOVER
    	if (Liberu.Robot == 1)
			try {
	            Liberu.output.write((byte)107);
	            Liberu.output.write('\n');
	            Liberu.output.write((byte)108);
	            Liberu.output.write('\n');
	            Liberu.output.write((byte)109);
	            Liberu.output.write('\n');
			}
	    	catch (Exception e) {
	            System.err.println(e.toString());
	    	}
	}
	
	public void emotionHappy() {
		short []happySound = {1963, 40};

		emotional = true;
    	BodyAct[Brain.Happy].setActive(true);
    	// Expres�o gen�tica de felicidade
    	if (Liberu.Robot == 2) {
    		happySound[0] = (short)(QF * 10 + 1000);
    		if (happySound[0] > 3000)
    			happySound[0] = 3000;
    		express(happySound); // NXT
    	}
    	if (Liberu.Robot == 1)
			try {
				Liberu.output.write((byte)104);
		        Liberu.output.write('\n');
			}
			catch (Exception e) {
		        System.err.println(e.toString());
			}
    	System.out.println(
    			"Emotion HAPPY...  :-)"); //REMOVER
	}
	
	public void emotionSad() {
		short []sadSound = {0403, 40};

		emotional = true;
    	BodyAct[Brain.Sad].setActive(true);
    	// Express�o gen�tica de tristeza
    	if (Liberu.Robot == 2) {
    		sadSound[0] = (short)(QF * 10 + 1000);
    		if (sadSound[0] < 20)
    			sadSound[0] = 20;
    		express(sadSound);
    	}
    	if (Liberu.Robot == 1)
			try {
	            Liberu.output.write((byte)105);
	            Liberu.output.write('\n');
			}
	    	catch (Exception e) {
	            System.err.println(e.toString());
	    	}
		System.out.println(
				"Emotion Sad...    :-("); //REMOVER
	}
	
	public void emotionPAIN() {

    	ActualPain   = true;
    	emotional = true;
    	if (BodyAct[Brain.Sad].active)
        	if (Liberu.Robot == 1 || Liberu.Robot == 2)
            	express(noteDor);
    	BodyAct[Brain.PAIN].setActive(true);
    	// Express�o gen�tica de Dor
		System.out.println(
				"Emotion PAIN...   ;-("); //REMOVER
	}

	public void emotionRIR() {

    	emotional = true;
    	rir		  = true;
    	if (Liberu.Robot == 1 || Liberu.Robot == 2)
        	express(noteRir);
    	if (Liberu.Robot == 0) {
			Mind.clip4.setMicrosecondPosition(0);
    		Mind.clip4.start();
    	}
		System.out.println(
				"Emotion RIR...   ;-)"); //REMOVER
	}

	public void emotionCHORAR() {

    	emotional = true;
    	choro	  = true;
    	if (Liberu.Robot == 1 || Liberu.Robot == 2)
        	express(noteChorar);
    	if (Liberu.Robot == 0) {
			Mind.clip5.setMicrosecondPosition(0);
    		Mind.clip5.start();
    	}
		System.out.println(
				"Emotion CHORAR...   :-#"); //REMOVER
	}

	public void emotionAfraid() {

    	emotional = true;
    	BodyAct[Brain.Afraid].setActive(true);
		System.out.println(
				"Emotion Afraid...   ,-("); //REMOVER
	}
			
	public void runEmotions() {
		int i, j; // indexes
		
    	try {
            stepBarrDecision.await(); // Sincroniza
        }
        catch(InterruptedException e) {
                e.printStackTrace();
            }
        catch (BrokenBarrierException ex) { 
            return;
        }
    	// ################################# DECIDE #######
    	Interface.Ink = 0;
        for (i=0; i<Brain.SENSES; i++) {
        	if (past.time[0][0].step > ActRandom) {
            	emotionNew(Remember.NewSense[i]);
        		if (i == Brain.Taste &&
        				Remember.NewSense[Brain.Taste] &&
        				!ActualPain)
        			IdAct1 = past.time[Good][i].
        			attentionOfFire(i);
        		if (i == Brain.Vision &&
        				Remember.NewSense[Brain.Vision] &&
        				!ActualPain)
        			IdAct1 = past.time[Good][i].
        			attentionOfFire(i);
        	}
		}
    	
    	QP = past.
    			time[past.time[0][0].
    			     pointer][Brain.ProSelf].finalQuality;
    	QR = past.
    			time[Math.abs(Good)][Brain.ProSelf].
    			finalQuality;
		System.out.println(QP);    // RETIRAR
		System.out.println(QR);    // RETIRAR
    	QF = QP + QR;
    	Interface.QF = QF;
        Normal = 0;
        for (i=0; i < past.nNeuronsTime; i++)
        	Normal += past.time[i]
        			[Brain.ProSelf].finalQuality;
        if (past.time[0][0].step <
        		past.nNeuronsTime &&
        		past.time[0][0].step != 0)
        	Normal = (int)(Normal /
        			past.time[0][0].step);
        else
        	Normal = (int)(Normal /
        			past.nNeuronsTime);
    	if (Normal >= 0)
        	if (QF < 0 && past.time[0][0].step > ActRandom)
            	emotionSad();
        	else {
            	if (QF > 2 * Normal &&
            			past.time[0][0].step > ActRandom)
                	emotionHappy();
        	}
    	else
        	if (QF < 2 * Normal &&
        			past.time[0][0].step > ActRandom)
            	emotionSad();
        	else {
            	if (QF > 0 &&
            			past.time[0][0].step > ActRandom)
                	emotionHappy();
        	}
    	if (QP < Cortex.lastQuality &&
    			past.time[0][0].step > ActRandom) {
    		emotionAfraid();
    		if (BodyAct[Brain.Happy].active)
    			emotionRIR();
    		else
    			if (BodyAct[Brain.Sad].active)
        			emotionCHORAR();
        		else
            		emotionSpeak();
    	}
		Cortex.lastQuality = QP;
        // ######  Recente decis�o ######
    	if (ActualPain && past.time[0][0].step > ActRandom)
    		// 
    		Good = -Good; // Ato oposto de reflexo de Dor 
		// ###############################
    	for (i=0; i<past.nNeuronsTime; i++)
        	for (j=0; j<past.time[i][0].learn.size();
        			j++) {
        		if (Math.abs(past.time[i][0].getLearn(j).
        				emitter) == past.time[i][0].
        				pointer)
        			past.time[i][0].removeLearn(j);
        	}
    	// ################################# ACT ##########
		System.out.print("Key****= "); // RETIRAR
		System.out.println(key); // RETIRAR
    	
    	while (!Brain.BusInAct.isEmpty())
    		Brain.BusInAct.poll();
        
        // ################## ALEAT�RIO - MENTOR ##########
    	try {
            stepBarrDecision2.await(); // sincroniza
        }
        catch(InterruptedException e) {
                e.printStackTrace();
            }
        catch (BrokenBarrierException ex) { 
            return; 
        }
        if (IdAct1 != Cerebellum.ESCape ||
        		past.time[0][0].step < ActRandom) {
        	if (IdAct1 != Cerebellum.ESCape) {
        		BodyAct[IdAct1].setActive(true);
        		BodyAct[IdAct1].setActPower(PwEm);
        		System.out.print("MentorA= "); //REMOVER
        		System.out.println(IdAct1); //REMOVER
        		Interface.Ink = 2; // Verde
        	}
        	else {
               	IdAct1 = (int)Math.rint(Math.random() *
               			(Brain.ACTS-1));
                if (past.time[0][0].step == 0) {
                	IdAct1 = Brain.WALK; // Primeira a��o
                }
        		BodyAct[IdAct1].setActive(true);
        		BodyAct[IdAct1].setActPower(PwEm);
        		System.out.print("Random1= "); //REMOVER
        		System.out.println(IdAct1); //REMOVER
        		Interface.Ink = 1; // Vermelho
        	}
    		past.actNode[IdAct1].standby = true;
        	IdAct1 = Cerebellum.ESCape; // Sem a��o
        }
        if (Liberu.Robot == 0 && idSound !=
        		Cerebellum.ESCape) {
    		past.actNode[idSound].standby = true;
        	idSound = Cerebellum.ESCape; // Sem a��o
        }

       	// ##################### R E L � G I O ############
        System.out.print("step= "); // REMOVER
       	System.out.println(past.time[0][0].pointer);
       								// REMOVER
    	if (!ActualPain) { // Incremento do passo sem Dor
           	for (j=0; j<Cortex.Senses; j++)
            	for (i=0; i<past.nNeuronsTime; i++) {
            		past.time[i][j].addStep();
            		// Rel�gio de vida do rob�
            		past.time[i][j].addPointer();
            		// Rel�gio da janela temporal do rob�
                	if ( past.time[i][j].pointer >
                	past.nNeuronsTime - 1)
                		past.time[i][j].setPointer(0);
            	}
        	for (i=0; i<past.nNeuronsTime; i++) {
        		past.hemisphereLeft[i].addStep();
        		// Rel�gio de vida do rob�
        		past.hemisphereLeft[i].addPointer();
        		// Rel�gio da janela temporal do rob�
            	if ( past.hemisphereLeft[i].pointer >
            	past.nNeuronsTime - 1)
            		past.hemisphereLeft[i].setPointer(0);
        		past.hemisphereRigth[i].addStep();
        		// Rel�gio de vida do rob�
        		past.hemisphereRigth[i].addPointer();
        		// Rel�gio da janela temporal do rob�
            	if ( past.hemisphereRigth[i].pointer >
            	past.nNeuronsTime - 1)
            		past.hemisphereRigth[i].setPointer(0);
        	}
    	}
    	// ############ Fim rel�gio #######################
        
        if (emotional) // Regresso ao estado normal
        	emotionNormal();
	}

    public void setLearn() {
    	int temp;
    	
		key = (String)text.getText().trim();
		Liberu.InterFace.repaint();
		System.out.print("Key= "); // RETIRAR
		System.out.println(key); // RETIRAR
		temp = Integer.parseInt(key);
		if (temp > 0 && temp < 65)
			if (key != "")
				Mind.local = temp;
		Liberu.InterFace.repaint();
		System.out.print("Local= "); // RETIRAR
		System.out.println(Mind.local); // RETIRAR
    }
	
    private class LearnListener implements
    DocumentListener {
    	
    	public void insertUpdate(DocumentEvent e)
    	{ setLearn(); }
    	public void removeUpdate(DocumentEvent e)
    	{ setLearn(); }
    	public void changedUpdate(DocumentEvent e) {}
    }
    
    public void run() {
        
		while(!stepBarrDecision.isBroken() &&
				!stepBarrDecision2.isBroken() &&
				!Neuron.end) {
    		runEmotions();
    	}
        System.out.println("End of Emotions Thread...");
    }
}