/*
 * Liberu.java
 *
 * Created on 30 of August 2005, 2:05
 */
/**
 * web site: www.vitaliberu.pt
 * email: sysliberal@gmail.com
 * @author Paulo Roque Silva
 */
import java.awt.*;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

import javax.swing.*;

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import icommand.nxt.Motor;

public class Liberu extends JFrame {
    
    public static final long serialVersionUID = 2026L;
    // Vers�o do Liberu
    static boolean  Already; // Pronto a mostrar
    static int		Robot;
    static Liberu	liberu;
    static Interface InterFace; // Interliga��o com mentor
    Mind            mind; // Mente a executar
    boolean			executed, // Se em execu��o
             		stopped, // Se parou
             		newUniverse, // Se novo universo
    				terminate, // Se pode new ou open
    				saved; // Se c�rtex guardado
	SerialPort      serialPort;
	public static String portaCOM = "COM3";
	public static BufferedReader input;
	public static String inputLine;
	public static OutputStream output;
   /** Milliseconds to block while waiting for port open */
	private static final int TIME_OUT = 2000;
	/** Default bits per second for COM port. */
	private static final int DATA_RATE = 9600;

    JTextField      text;           // Texto lido
    JPanel          panel;          // Window
	String			directory = "", // Diretoria defeito
					file = ""; // Ficheiro in�cio
    
    /** Creates new form Liberu */
    public Liberu() {
        int screenWidth;
        int screenHeight;
        
        // Get Screen dimensions
        Toolkit kit = Toolkit.getDefaultToolkit();
        Dimension screenSize = kit.getScreenSize();
        screenWidth = screenSize.width;
        screenHeight = screenSize.height;
        // Center frame in Screen
        setLocation( screenWidth / 8, screenHeight / 8 );
        // Set frame icon
        Image img = kit.getImage("Brain.gif");
        setIconImage(img);

        Already     = false;
        Robot       = 0;
        executed    = false;
 		stopped     = true;
 		newUniverse = true;
 		terminate   = true;
	    text         = new JTextField(6);
	    text.setText("local");
        InterFace   = new Interface();
        mind  		= new Mind(false, text);
	    mind.display(false, false);
        initComponents();
        if (screenWidth > 2000)
            setSize( 2*768, 2*600);
        else
            setSize( 768, 600);
        saved       = true;
        
	    panel        = new JPanel();
		panel.add(text);
        getContentPane().add(panel, BorderLayout.SOUTH);
    }
    
	protected void processWindowEvent(WindowEvent e) {

		if (e.getID() == WindowEvent.WINDOW_CLOSING) {
	        if (!saved) {
	            if (JOptionPane.showConfirmDialog(null,
      "The Robot's Cortex not saved! Do you want to exit?",
      "Alert", JOptionPane.OK_CANCEL_OPTION) ==
      JOptionPane.OK_OPTION)
	            	exitLiberu();
	        }
	        else
	        	exitLiberu();
		}
	}
	
	public static String inputLine() {
		
		return inputLine;
	}

    public synchronized void close() {
		
        if (serialPort != null) {
//            serialPort.removeEventListener();
            serialPort.close();
    	}
    }

    public synchronized void serialEvent(
    		SerialPortEvent oEvent) {
		
        if (oEvent.getEventType() == SerialPortEvent.
        		DATA_AVAILABLE) {
            try {
                String inputLine=input.readLine();
                //  ###############################
                System.out.println(inputLine); // RETIRAR
            } catch (Exception e) {
                System.err.println(e.toString());
            }
        }
    }

    private void initComm() {
    	
    	// TODO code application logic here
        System.setProperty("gnu.io.rxtx.SerialPorts",
        		portaCOM);

        try {
            CommPortIdentifier portId = CommPortIdentifier.
            		getPortIdentifier(portaCOM);
            if (portId == null) {
                    System.out.println(
                    		"Could not find COM port.");
                    return;
            }

            serialPort = (SerialPort) portId.open(
            		this.getClass().getName(), TIME_OUT);

        	// set port parameters
            serialPort.setSerialPortParams(DATA_RATE,
            		SerialPort.DATABITS_8,
            		SerialPort.STOPBITS_1,
            		SerialPort.PARITY_NONE);

        	// open the streams
            input = new BufferedReader(
            		new InputStreamReader(serialPort.
            				getInputStream()));
            output = serialPort.getOutputStream();

        	// add event listeners
//                serialPort.addEventListener(this);
//                serialPort.notifyOnDataAvailable(true);
        } catch (Exception e) {
                System.err.println(e.toString());
        }
    	System.out.println("Started");
    }
	
    private void initComponents() {
        jPanel1     = new JPanel();
        JPanel        panel; // Window
        jButton0    = new JButton();
        jButton1    = new JButton();
        jButton2    = new JButton();
        jButton3    = new JButton();
        jButton4    = new JButton();
        jButton5    = new JButton();
        jButton6    = new JButton();
        jMenuBar1   = new JMenuBar();
        jMenu1      = new JMenu();
        jMenu3      = new JMenu();
        jMenuItem1  = new JMenuItem();
        jMenuItem2  = new JMenuItem();
        jMenuItem3  = new JMenuItem();
        jMenuItem31 = new JMenuItem();
        jSeparator1 = new JSeparator();
        jMenuItem4  = new JMenuItem();
        jButton2Act = new JButton();
        jButton3Act = new JButton();
        jButton4Act = new JButton();
        jButtonDAct = new JButton();
        jButtonHAct = new JButton();
        jLabel1 = new JLabel("Liberu:");
        jLabel2 = new JLabel("Sr. Mouse:");
        jLabel3 = new JLabel("Thumb:");

        setDefaultCloseOperation(
        		WindowConstants.EXIT_ON_CLOSE);
        setTitle(
            	"VitaLiberu 2026 - Vita-Mouse "
        		+ " - "	+ directory + file);
        jPanel1.add(jLabel1);
        jButton0.setText("Simulation");
        jButton0.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                typeAction(evt);
            }
        });
        jPanel1.add(jButton0);

        jPanel1.add(jLabel3);

        if (!Cortex.Born) {
            jButton6.setText("Right Up");
            jButton6.setBackground(Color.GREEN);
        }
        else
        	if (Cortex.Thumb) {
                jButton6.setBackground(Color.RED);
                jButton6.setText("Left  Up");
        	}
        	else {
                jButton6.setBackground(Color.GREEN);
                jButton6.setText("Right Up");
        	}
        jButton6.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                thumbAction(evt);
            }
        });
        jPanel1.add(jButton6);

        jPanel1.add(jLabel1);
        jButton1.setText("Play");
        jButton1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                playAction(evt);
            }
        });
        jPanel1.add(jButton1);

        jButton2.setText("Warn");
        jButton2.setBackground(Color.GREEN);
        jButton2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                warnAction(evt);
            }
        });
        jPanel1.add(jButton2);

        jButton3.setText("Pause");
        jButton3.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                pauseAction(evt);
            }
        });
        jPanel1.add(jButton3);

        jButton4.setText("Continue");
        jButton4.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                continueAction(evt);
            }
        });
        jPanel1.add(jButton4);

        jButton5.setText("Stop");
        jButton5.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                stopAction(evt);
            }
        });
        jPanel1.add(jButton5);

        getContentPane().add(jPanel1, BorderLayout.NORTH);

        jMenu1.setText("Cortex");
        jMenuItem1.setText("New Cortex");
        jMenuItem1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                newAction(evt);
            }
        });
        jMenu1.add(jMenuItem1);

        jMenuItem2.setText("Open Cortex...");
        jMenuItem2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                openAction(evt);
            }
        });
        jMenu1.add(jMenuItem2);

        jMenuItem3.setText("Save Cortex...");
        jMenuItem3.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                saveAction(evt);
            }
        });
        jMenu1.add(jMenuItem3);

        jMenu1.add(jSeparator1);

        jMenuItem4.setText("Exit Liberu");
        jMenuItem4.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                exitAction(evt);
            }
        });
        jMenu1.add(jMenuItem4);
        jMenuBar1.add(jMenu1);

        jMenu3.setText("Help"); 
        jMenuItem31.setText("Version..."); 
        jMenuItem31.addActionListener(
        		new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                versionAction(evt);
            }
        });
        jMenu3.add(jMenuItem31);
        jMenuBar1.add(jMenu3);

        setJMenuBar(jMenuBar1);
        getContentPane().add(Liberu.InterFace,
        		BorderLayout.CENTER);
	    panel        = new JPanel(new GridLayout(16, 1));

	    
	    getContentPane().add(panel, BorderLayout.EAST);

        panel.add(jLabel2);

        jButton2Act.setText("Walk");
        jButton2Act.addActionListener(
        		new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                walkAction(evt);
            }
        });
        panel.add(jButton2Act);
    

        jButton3Act.setText("Left");
        jButton3Act.addActionListener(
        		new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                leftAction(evt);
            }
        });
        panel.add(jButton3Act);

        jButton4Act.setText("Right");
        jButton4Act.addActionListener(
        		new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                rightAction(evt);
            }
        });
        panel.add(jButton4Act);

        jButtonDAct.setText("Energy");
        jButtonDAct.setBackground(Color.CYAN);
        jButtonDAct.addActionListener(
        		new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                energyAction(evt);
            }
        });
        panel.add(jButtonDAct);

        jButtonHAct.setText("Home");
        jButtonHAct.setBackground(Color.GREEN);
        jButtonHAct.addActionListener(
        		new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                homeAction(evt);
            }
        });
        panel.add(jButtonHAct);

        pack();
    }

    private void newAction(ActionEvent evt) {
    	int i;
    	
    	if (stopped && terminate) {
    		mind = new Mind(false, text);
    		mind.display(false, false);
            newUniverse = true;
    		Cortex.Born = false;
            for (i=0; i<Interface.Vision.length; i++)
            	Interface.Vision[i] = 0;
            for (i=0; i<Interface.Sound.length; i++)
            	Interface.Sound[i] = 0;
            for (i=0; i<Interface.Smell.length; i++)
            	Interface.Smell[i] = 0;
            Interface.Lovely = 0;
            Interface.QF = 0;
            JOptionPane.showMessageDialog(null,
            		"New Liberu!", "Information",
                JOptionPane.INFORMATION_MESSAGE);
        }
    }

    private void warnAction(ActionEvent evt) {
    	int i; // index
    	
        if (executed)
        	Cortex.Warn = !Cortex.Warn;
    	if (Cortex.Warn) {
            jButton2.setBackground(Color.RED);
	        for (i=0; i < Brain.SENSES; i++)
	        	Interface.WarnSense[i] = false;
    	}
    	else {
            jButton2.setBackground(Color.GREEN);
	        for (i=0; i < Brain.SENSES; i++)
	        	Interface.WarnSense[i] = false;
    	}
    }

    private void thumbAction(ActionEvent evt) {

        if (!executed && stopped)
        	Cortex.Thumb = !Cortex.Thumb;
    	if (Cortex.Thumb) {
            jButton6.setBackground(Color.RED);
            jButton6.setText("Left  Up");
    	}
    	else {
            jButton6.setBackground(Color.GREEN);
            jButton6.setText("Right Up");
    	}
    }

    private void pauseAction(ActionEvent evt) {

        if (executed) {
        	mind.pause();
            if (Robot == 1)
        		try {
                    output.write((byte)113);
                    output.write('\n');
        		}
            	catch (Exception e) {
                    System.err.println(e.toString());
            	}
            if (Robot == 2) {
            	Motor.A.stop();
            	Motor.B.stop();
            }
        }
    }

    private void continueAction(ActionEvent evt) {

    	if (executed) {
            stopped = false;
            mind.continueRun();
        }
    }

    private void exitLiberu() {
    	
    	if (executed) {
            if (Robot == 1)
        		try {
                    output.write((byte)113);
                    output.write('\n');
        		}
            	catch (Exception e) {
                    System.err.println(e.toString());
            	}
            if (Robot == 2) {
            	Motor.A.stop();
				Motor.B.stop();
            }
        	mind.brain.endLiberu(true);
	        Neuron.end = true;
	        mind.setToEnd(); // P�e neur�nios em fim
	        mind.interrupt();
        }
        System.out.println("END Liberu...bye bye");
        System.exit(0);
    }
    
    private void exitAction(ActionEvent evt) {

        if (!saved) {
            if (JOptionPane.showConfirmDialog(null,
            	"The Robot's Cortex not, yet, saved! " +
            	"Do you want to exit?",
            	"Alert", JOptionPane.OK_CANCEL_OPTION) ==
            	JOptionPane.OK_OPTION)
            	exitLiberu();
        }
        else
        	exitLiberu();
    }

    private void saveAction(ActionEvent evt) {
		File		fout;
		FileDialog 	fd;
        
    	if (terminate) {
    		fd = new FileDialog(this, "File to Save?",
    				FileDialog.SAVE);
    		fd.setVisible(true);
    		if (fd.getDirectory() != null &&
    				fd.getFile() != null) {
    			directory = fd.getDirectory();
    			file = fd.getFile();
    		}
    		fout = new File(directory + file);
	        try {
	            // Guarda c�rtex
	            ObjectOutputStream out =
	            		new ObjectOutputStream(
	            			new FileOutputStream(fout));
	            out.writeObject(mind.brain.past);
	            out.close();
	            saved = true;
	            setTitle(
	                	"VitaLiberu 2026 - Vita-Mouse "
	            		+ " - "	+ directory + file);
	        }
	        catch (Exception e) {
	            e.printStackTrace();
	        }
        }
    }

    private void openAction(ActionEvent evt) {
		File		fin;
		FileDialog 	fd;
        
    	if (stopped && terminate) {
    		fd = new FileDialog(this, "File to Load?",
    				FileDialog.LOAD);
    		fd.setVisible(true);
    		if (fd.getDirectory() != null &&
    				fd.getFile() != null) {
    			directory = fd.getDirectory();
    			file = fd.getFile();
    		}
    		fin = new File(directory + file);
    		if (fin.exists()) {
    	        try {
    	            // L� c�rtex
    	            ObjectInputStream in =
    	            		new ObjectInputStream(
    	            			new FileInputStream(fin));
    	    		mind = new Mind(true, text);
    	            mind.brain.past =
    	            		(Cortex)in.readObject();
        	        Neuron.end = false;
                    newUniverse = true;
                    mind.display(true, false);
    	            in.close();
    	            setTitle(
    	                	"VitaLiberu 2026 - Vita-Mouse "
    	            		+ " - "	+ directory + file);
    	        }
                catch (Exception e) {
                    e.printStackTrace();
                }
    		}
        }
    }

    private void playAction(ActionEvent evt) {

    	if (!executed && newUniverse) {
    		Cortex.Born = true;
            executed = true;
            terminate = false;
            stopped = false;
            if (Robot == 1)
            	liberu.initComm();  // Formica
            mind.step(false);
            mind.setDaemon(true);
            mind.start();
            mind.display(true, false);
            newUniverse = false;
            saved = false;
        }
    }
    
    private void stopAction(ActionEvent evt) {

    	if (executed) {
            if (JOptionPane.showConfirmDialog(null,
                    "The Robot is going to Stop...",
                    "Alert",
                    JOptionPane.OK_CANCEL_OPTION) ==
                    JOptionPane.OK_OPTION) {
            	mind.setToEnd(); // P�e neur�nios para fim
            	mind.brain.endLiberu(true);
            	mind.interrupt();
                executed = false;
                stopped = true;
                terminate = true;
                mind.line.close();
            }
        }
    }

    private void versionAction(ActionEvent evt) {

        JOptionPane.showMessageDialog(null,
        		"Liberu, by Paulo Roque Silva... " +
        	"2004-2026 www.VitaLiberu.pt"
        		+ " - Formica A - " + Brain.NEURONS +
        		" neurons", "Information\n",
                JOptionPane.INFORMATION_MESSAGE);
    }

    private void walkAction(ActionEvent evt) {

    	if (executed) {
    		mind.brain.idAct1(Brain.WALK);
    	}
    }

    private void leftAction(ActionEvent evt) {

    	if (executed) {
    		mind.brain.idAct1(Brain.TURN_LEFT);
    	}
    }

    private void rightAction(ActionEvent evt) {

    	if (executed) {
    		mind.brain.idAct1(Brain.TURN_RIGHT);
    	}
    }

    private void energyAction(ActionEvent evt) {
    	
    	if (executed)
        	Brain.Energy = !Brain.Energy;
    	if (executed && Brain.Energy) {
            jButtonDAct.setBackground(Color.RED);
    	}
    	if (executed && !Brain.Energy) {
            jButtonDAct.setBackground(Color.CYAN);
    	}
    }

    private void homeAction(ActionEvent evt) {
    	
    	if (executed)
        	Brain.BackHome = !Brain.BackHome;
    	if (executed && Brain.BackHome) {
            jButtonHAct.setBackground(Color.RED);
    	}
    	if (executed && !Brain.BackHome) {
            jButtonHAct.setBackground(Color.GREEN);
    	}
    }

    private void typeAction(ActionEvent evt) {
    	
    	if (!executed && stopped) {
        	Robot += 1;
        	if (Robot > 2)
        		Robot = 0;
    	}
    	if (!executed && Robot == 1) {
            jButton0.setText("Mouse");
    	}
    	if (!executed && Robot == 0) {
            jButton0.setText("Simulation");
    	}
    	if (!executed && Robot == 2) {
            jButton0.setText("NXT");
    	}
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[])
    		throws Exception {

    	EventQueue.invokeLater(new Runnable() {
    		public void run() {
            	liberu = new Liberu();
            	liberu.setVisible(true);
        		if (args.length > 0)
                	Liberu.portaCOM = (String)args[0];
            }
        });
    }    
    private JButton    jButton0;
    private JButton    jButton1;
    private JButton    jButton2;
    private JButton    jButton3;
    private JButton    jButton4;
    private JButton    jButton5;
    private JButton    jButton6;
    private JMenu      jMenu1;
    private JMenu      jMenu3;
    private JMenuBar   jMenuBar1;
    private JMenuItem  jMenuItem1;
    private JMenuItem  jMenuItem2;
    private JMenuItem  jMenuItem3;
    private JMenuItem  jMenuItem4;
    private JMenuItem  jMenuItem31;
    private JPanel     jPanel1;
    private JSeparator jSeparator1;
    private JButton    jButton2Act;
    private JButton    jButton3Act;
    private JButton    jButton4Act;
    public static JButton    jButtonDAct;
    public static JButton    jButtonHAct;
    private JLabel	   jLabel1;
    private JLabel	   jLabel2;
    private JLabel	   jLabel3;
}