package makerosc;

import java.lang.System;
import java.text.*;
import java.awt.*;
import java.awt.Color.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.BindException;
import java.net.UnknownHostException;
import com.illposed.osc.*;
//import com.illposed.osc.utility.*;

//rpm = 60* frequency of rising edges/# teeth



public class JMake extends JFrame
{
	JFrame mainFrame;
	JPanel mPane;
    static final long serialVersionUID= 0; 
 	public static String strDefaultHostName;
	public static InetAddress ina;
	private static OSCPortIn receiver;
	Boolean hasSocket;
	
	static JTextField system_name;
	static JTextField system_freememory;

	static JCheckBox appled1;
	static JCheckBox appled2;
	static JCheckBox appled3;
	static JCheckBox appled4;
	static JRadioButton rb1;
	static JRadioButton rb2;
	static JRadioButton rb3;
	static JRadioButton rb4;
	
	static JToggleButton btn_motor;
	static JToggleButton btn_actuator;	
	static JTextField tf_tach;
	
	static long timeold;
	static double rpm;
	static final int NUMBER_OF_MAGNETS=32;
	static long[][] data; 
	static int npts;
	
	RPMTracker rpmt = new RPMTracker();
	
	public JMake(Boolean isConnected )
	{ 
		Border brd_cmpnd= BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(),
    		BorderFactory.createLoweredBevelBorder());
		
		mainFrame = new JFrame();
		mainFrame.setTitle( "Make Controller Control Panel" );
		mainFrame.setSize( 600, 400 );
		mainFrame.setBackground( Color.gray );	

		mPane=new JPanel();
		mPane.setLayout( null ); 
		
		// NOTE: to reduce the amount of code in this example, it uses
		// panels with a NULL layout.  This is NOT suitable for
		// production code since it may not display correctly for
		// a look-and-feel.

		try {
			startlistener();
		 } catch (BindException e) {
				e.printStackTrace();
				 hasSocket=false;
		 } catch (SocketException e) {
				e.printStackTrace();
				 hasSocket=false;
		} finally {
			hasSocket=true;	
		}

		if (isConnected & hasSocket) {
			JLabel label0 = new JLabel( "Connected: TCP/IP and Socket" );
			label0.setBounds( 10, 5, 500, 20 );
			mPane.add( label0 );
		} else if (isConnected & !hasSocket) {
			JLabel label0 = new JLabel( "Connected: TCP/IP but no Socket (Not connected)" );
			label0.setBounds( 10, 5, 500, 20 );
			mPane.add( label0 );	
		} else  {
			JLabel label0 = new JLabel( "Not Connected: No TCP/IP ");
			label0.setBounds( 10, 5, 500, 20 );
			mPane.add( label0 );	
		}

		// System
		JLabel label1 = new JLabel( "Name:" );
		label1.setBounds( 10, 15, 150, 20 );
		mPane.add( label1 );

		system_name = new JTextField();
		system_name.setBounds( 10, 35, 150, 20 );
		mPane.add( system_name );

		JButton btn_system = new JButton("System Name");
		btn_system.setBounds(200, 35, 150, 20 );
		btn_system.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e){
					sendmsg("/system/name",new Object[1]);
				}
		});
		mPane.add( btn_system );
		
		JLabel label2 = new JLabel( "Free Memory:" );
		label2.setBounds( 10, 60, 150, 20 );
		mPane.add( label2 );

		system_freememory = new JTextField();
		system_freememory.setBounds( 10, 80, 150, 20 );
		mPane.add( system_freememory );
		
		JButton btn_freememory = new JButton("System Free Memory");
		btn_freememory.setBounds(200, 80, 150, 20 );
		btn_freememory.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e){
					sendmsg("/system/freememory",new Object[1]);
				}
		});
		mPane.add( btn_freememory );
		
		
		JLabel label3 = new JLabel( "Task Report:" );
		label3.setBounds( 10, 105, 150, 20 );
		mPane.add( label3 );

		JTextArea system_taskreport = new JTextArea();
		system_taskreport.setBounds(10, 125, 300, 40 );
		mPane.add( system_taskreport );
		
		// AppLED
		rb1 = new JRadioButton();
			rb1.setEnabled(true) ;
			rb1.setForeground(Color.green);
		rb2 = new JRadioButton();
			rb2.setEnabled(true) ;
		rb3 = new JRadioButton();
			rb3.setEnabled(true) ;
		rb4 = new JRadioButton();
			rb4.setEnabled(true) ;
		
		appled1 = new JCheckBox("1");
		appled1.setHorizontalTextPosition(SwingConstants.LEFT);
	    appled1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				Object argx[] = new Object[1];	    	
				if (appled1.isSelected()) {
					argx[0]=new Integer(1);
					sendmsg("/appled/0/state",argx);
				} else {
					argx[0]=new Integer(0);
					sendmsg("/appled/0/state",argx);
				}
			}
	    });		
		appled2 = new JCheckBox("2");
		appled2.setHorizontalTextPosition(SwingConstants.LEFT);
	    appled2.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
		    	Object argx[]=new Object[1];
				if (appled2.isSelected()) {
					argx[0]=new Integer(1);
					sendmsg("/appled/1/state",argx);
				} else{
					argx[0]=new Integer(0);
					sendmsg("/appled/1/state",argx);
				}
			}
	    });		    
		appled3 = new JCheckBox("3");
		appled3.setHorizontalTextPosition(SwingConstants.LEFT);
	    appled3.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
		    	Object argx[]=new Object[1];
				if (appled3.isSelected()) {
					argx[0]=new Integer(1);
					sendmsg("/appled/2/state",argx);
				} else{
					argx[0]=new Integer(0);
					sendmsg("/appled/2/state",argx);
				}
			}
	    });		    
		appled4 = new JCheckBox("4");
		appled4.setHorizontalTextPosition(SwingConstants.LEFT);
	    appled4.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
		    	Object argx[]=new Object[1];
				if (appled4.isSelected()) {
					argx[0]=new Integer(1);
					sendmsg("/appled/3/state",argx);
				} else{
					argx[0]=new Integer(0);
					sendmsg("/appled/3/state",argx);
				}
			}
	    });		    
	    
	    JPanel jp = new JPanel(new GridLayout(4,2,10,10));
	    jp.setBorder(brd_cmpnd);   
		//jp.setBackground( Color.blue );	    
	    jp.add(appled1);jp.add(rb1);
	    jp.add(appled2);jp.add(rb2);
	    jp.add(appled3);jp.add(rb3);
	    jp.add(appled4);jp.add(rb4);
	    jp.setBounds(400, 35, 100, 130);
	    mPane.add(jp);
	    
	    //Motor, Linear Actuator & Magnetic Sensor Tachometer
	    JPanel jpmotor = new JPanel(new GridLayout(1,4,10,10));
	    jpmotor.setBounds(10,180,300,40);
	    jpmotor.setBorder(brd_cmpnd);   
		btn_motor = new JToggleButton("Motor");
		btn_motor.setBounds(200, 35, 150, 20 );
		btn_motor.addActionListener(new ActionListener(){
			 public void actionPerformed(ActionEvent e){
			    Object argx[]=new Object[1];
				if (btn_motor.isSelected()) {
					argx[0]=new Integer(1);
					sendmsg("/digitalout/4/value",argx);
					timeold=System.currentTimeMillis();
				} else {
					argx[0]=new Integer(0);
					sendmsg("/digitalout/4/value",argx);
				}
			 }
		});
		btn_actuator = new JToggleButton("Actuator");
		btn_actuator.addActionListener(new ActionListener(){
			 public void actionPerformed(ActionEvent e){
			    Object argx[]=new Object[1];
				if (btn_actuator.isSelected()) {
					argx[0]=new Integer(0);
					sendmsg("/digitalout/1/value",argx);
				} else {
					argx[0]=new Integer(1);
					sendmsg("/digitalout/1/value",argx);
				}
			 }
		});	
		
		tf_tach = new JTextField(50);
		jpmotor.add(btn_motor);
		jpmotor.add(btn_actuator);
		jpmotor.add(tf_tach);
		mPane.add( jpmotor );	    
	    
	    //initialize variables
		timeold=System.currentTimeMillis();
		data=new long[6000][2];
		npts=0;
		
		mainFrame.getContentPane().add(mPane,BorderLayout.CENTER);
		mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//mainFrame.pack();
		mainFrame.setVisible( true );
		
		//Check Status
		sendmsg("/appled/*/state");
		
		//Set autosend
		Object a[]=new Object[1];
		a[0]=1; // send over ethernet;
		sendmsg("/system/autosend-udp",a);
		a[0]=10;
		sendmsg("/system/autosend-interval",a);
		a[0]=1;
		sendmsg("/analogin/4/autosend",a);
		sendmsg("/analogin/4/active");
		
		
		//add hyperlink button to source
		   // http://www.makingthings.com/ref/firmware/html/group___system_o_s_c.html
		   // * name
		   // * freememory

		
		   addWindowListener(new WindowAdapter()
		    {
		       public void windowClosing(WindowEvent e)
		       {
		    	 System.out.println("Goodbye World! From JMake"); //Display the string.
		     	 if (receiver.isListening()) {
		     		 receiver.stopListening();
		     	 }
		         dispose();
		         System.exit(0); //calling the method is a must
		       }
		    });		
	}
	
	public static void startlistener()  throws SocketException {
		   System.out.println("Hello World! From startlistener()"); //Display the string.
		 	receiver = new OSCPortIn(10004);
		 	OSCListener listener = new OSCListener() {    	  	        		
		    	public void acceptMessage(java.util.Date time, OSCMessage message) {
		    		int im;
		 	   		for (int i=0;i<message.getArguments().length;i++){
						System.out.println("rec'd: "+" "+message.getAddress()+" <"+message.getArguments()[i]+">");
						String msg =message.getAddress();
						       if (msg.compareToIgnoreCase("/system/name")==0){
							 system_name.setText((String)message.getArguments()[0]);
		 	   			} else if (msg.compareToIgnoreCase("/system/freememory")==0) {
							 system_freememory.setText(message.getArguments()[0].toString());
		 	   			} else if (msg.compareToIgnoreCase("/analogin/4/value")==0) {
		 	   				Integer v=(Integer)message.getArguments()[0];
		 	   				String tstr=v.toString();
		 	   				// with each sensor
		 	   				data[npts][0]=(long)((Integer)message.getArguments()[0]);
		 	   				data[npts][1]=(long)System.currentTimeMillis();
		 	   				npts++;
		 	   				if (v>700){
		 	   					tf_tach.setBackground(new Color(255,0,0));
		 	   					double rpmcount=1;
		 	   					long elapsed=System.currentTimeMillis()-timeold;
		 	   					rpm=(NUMBER_OF_MAGNETS*10)/(elapsed)*rpmcount;
		 	   					timeold=System.currentTimeMillis();
		 	   					System.out.println("/analogin/4/value "+tstr);
		 	   					tf_tach.setText(new DecimalFormat("##.##").format(rpm));
		 	   				} else {
			 	   				tf_tach.setBackground(new Color(0,255,0)); 	   					
		 	   				}
		 	   			} else if (msg.compareToIgnoreCase("/analogin/4/active")==0) {
		 	   				String tstr=(message.getArguments()[0]).toString();
		 	   				System.out.println("/analogin/4/active "+tstr);
		 	   			} else if (msg.compareToIgnoreCase("/appled/0/state")==0) {
		 	   				im=(Integer)message.getArguments()[0];
		 	   				rb1.setSelected(1==im?true:false);
						 	appled1.setSelected(1==im?true:false); 
		 	   			} else if (msg.compareToIgnoreCase("/appled/1/state")==0) {
		 	   				im=(Integer)message.getArguments()[0];
		 	   				rb2.setSelected(1==im?true:false);
						 	appled2.setSelected(1==im?true:false); 
		 	   			} else if (msg.compareToIgnoreCase("/appled/2/state")==0) {
		 	   				im=(Integer)message.getArguments()[0];
		 	   				rb3.setSelected(1==im);
						 	appled3.setSelected(1==im); 
		 	   			} else if (msg.compareToIgnoreCase("/appled/3/state")==0) {
		 	   				im=(Integer)message.getArguments()[0];
		 	   				rb4.setSelected(1==im);
						 	appled4.setSelected(1==im); 
						} else {
							System.out.println("Listener - default");
						}
		 			}
		    	}
		   };
		    receiver.addListener("/analogin/4/value",listener);
		    receiver.addListener("/analogin/4/active",listener);
		    receiver.addListener("/system",listener);
		    receiver.addListener("/system/name",listener);
		    receiver.addListener("/system/freememory",listener);
		    receiver.addListener("/appled/0/state",listener);
		    receiver.addListener("/appled/1/state",listener);
		    receiver.addListener("/appled/2/state",listener);
		    receiver.addListener("/appled/3/state",listener);
		    receiver.startListening();
		    	        
		    try {
		    	Thread.sleep(5000);// 1000 < sleep <= 4000
		    } catch (InterruptedException e) {
		    	// TODO Auto-generated catch block
		    	e.printStackTrace();
		    }
	}   

	public static void sendmsg(String strmsg)
	{
	 	 System.out.println("Request from sentmsg() (no argx)"+strmsg); //Display the string.		
		Object argx[] = new Object[1];
		sendmsg(strmsg,argx);
	}
	public static void sendmsg(String strmsg,Object argx[]) {
		if (argx.length>0){ 
			if (argx[0]!=null){
				System.out.println("From sendmsg()"+strmsg+" argx: "+((Integer)argx[0]).toString()); //Display the string.		
		}}
  		try {
  			OSCPortOut sender = new OSCPortOut(ina,10000);
  	  		OSCMessage msg = new OSCMessage(strmsg,argx);
			//System.out.print(" sending... >");
 	   		//for (int i=0;i<msg.getArguments().length;i++){
			//	System.out.print(msg.getArguments()[i]+" ");
			//}
			//System.out.println(" <...");
			sender.send(msg);
  		} catch (SocketException e) {
  				 System.out.println("**"+e.toString());
  		} catch (UnknownHostException e){    
  				 System.out.println(e.toString());
  		} catch (IOException e){    
  			System.out.println(e.toString());
   		}
     } 
 
    // Main method to get things started
	public static void main( String args[] )
	{	
        try {
        	strDefaultHostName="192.168.0.200";
			ina = InetAddress.getByName(strDefaultHostName);
		} catch (UnknownHostException e) {
			e.printStackTrace();
			JMake mainFrame	= new JMake(false);
		} finally {
			JMake mainFrame = new JMake(true);
		}
	}
}

