/*------------------------------------------------------------------------------------
   Program:     port_select

   Description: Allows a serial port to be selected and connected to graphically.
                Has the following buttons:
                Up         - scrolls up through the serial port list 
                Down       - scrolls down through the serial port list
                Connect    - connects to the selected serial port
                Disconnect - disconnects from the serial port allowing a new serial
                             port to be connected to
                Refresh    - refreshes the list of serial ports. Useful if a new
                             serial device is connected to the PC after this app-
                             lication is started
                
   Purpose:     Allows the serial port to be selected within an application instead
                of hard-coding the port number
                
   Hardware:    Can be used to connect to Arduino or other serial devices
   
   Software:    Developed using Processing 2.2.1 (processing.org)
                Uses the Button class from:
                http://blog.startingelectronics.com/a-simple-button-for-processing-language-code/
                
   Date:        21 July 2015   Author:   W.A. Smith, http://startingelectronics.org
   
------------------------------------------------------------------------------------*/

import processing.serial.*;
import interfascia.*;

GUIController c;
IFTextField tpause;
IFLabel lpause;
IFTextField tvalues;
IFLabel lvalues;

Serial serial_port = null;        // the serial port

// serial port buttons
Button btn_serial_up;              // move up through the serial port list
Button btn_serial_dn;              // move down through the serial port list
Button btn_serial_connect;         // connect to the selected serial port
Button btn_serial_disconnect;      // disconnect from the serial port
Button btn_serial_list_refresh;    // refresh the serial port list

// other buttons
Button btn_serial_STOP;
Button btn_serial_IX;
Button btn_serial_IZ;
Button btn_serial_mup;              
Button btn_serial_mdn;
Button btn_serial_mlft;              
Button btn_serial_mrgt;
Button btn_proceed;



String serial_list;                // list of serial ports
int serial_list_index = 0;         // currently selected serial port 
int num_serial_ports = 0;          // number of serial ports in the list

float posX;                          // X position
float posZ;                          // Z position

String inString;  // Input string from serial port
int lf = 10;      // ASCII linefeed

void setup() {
  // set the window size
  size (640, 480);
  background(51);
  
  c = new GUIController(this);
  lpause = new IFLabel("Pause duration / seconds", 10, 280);
  tpause = new IFTextField("pause", 10, 300, 60, "");
  lvalues = new IFLabel("X positions list, in cm, separated with ;", 10, 340);
  tvalues = new IFTextField("xvalues", 10, 360, 620, "");

  
  // create the buttons
  btn_serial_up = new Button("^", 340, 50, 40, 20);
  btn_serial_dn = new Button("v", 340, 80, 40, 20);
  btn_serial_connect = new Button("Connect", 500, 60, 100, 25);
  btn_serial_disconnect = new Button("Disconnect", 500, 90, 100, 25);
  btn_serial_list_refresh = new Button("Refresh", 500, 30, 100, 25);
  btn_serial_IX = new Button("IX", 20, 200, 100, 25);
  btn_serial_IZ = new Button("IZ", 20, 160, 100, 25);
  btn_serial_STOP = new Button("STOP", 364,188, 50, 25);
  btn_serial_mup = new Button("^", 370, 160, 40, 20);
  btn_serial_mdn = new Button("v", 370, 220, 40, 20);
  btn_serial_mlft = new Button("<", 320, 190, 40, 20);
  btn_serial_mrgt = new Button(">", 420, 190, 40, 20); 
  btn_proceed = new Button("PROCEED", 300, 400, 80, 25); 
 
  // get the list of serial ports on the computer
  serial_list = Serial.list()[serial_list_index];
  
  //println(Serial.list());
  //println(Serial.list().length);
  
  // get the number of serial ports in the list
  num_serial_ports = Serial.list().length;
 
  c.add(tpause);
  c.add(lpause);
  c.add(tvalues);
  c.add(lvalues);
  tpause.addActionListener(this);
  tvalues.addActionListener(this);
  
  
}

void mousePressed() {
  // up button clicked
  if (btn_serial_up.MouseIsOver()) {
    if (serial_list_index > 0) {
      // move one position up in the list of serial ports
      serial_list_index--;
      serial_list = Serial.list()[serial_list_index];
    }
  }
  // down button clicked
  if (btn_serial_dn.MouseIsOver()) {
    if (serial_list_index < (num_serial_ports - 1)) {
      // move one position down in the list of serial ports
      serial_list_index++;
      serial_list = Serial.list()[serial_list_index];
    }
  }
  // Connect button clicked
  if (btn_serial_connect.MouseIsOver()) {
    if (serial_port == null) {
      // connect to the selected serial port
      serial_port = new Serial(this, Serial.list()[serial_list_index], 115200);
      println("connected");
      serial_port.bufferUntil(lf);
    }
  }
  // Disconnect button clicked
  if (btn_serial_disconnect.MouseIsOver()) {
    if (serial_port != null) {
      // disconnect from the serial port
      serial_port.stop();
      serial_port = null;
    }
  }
  // Refresh button clicked
  if (btn_serial_list_refresh.MouseIsOver()) {
    // get the serial port list and length of the list
    serial_list = Serial.list()[serial_list_index];
    num_serial_ports = Serial.list().length;
  }
  // S button clicked
     if (serial_port != null) {
         if (btn_serial_STOP.MouseIsOver()) {
            serial_port.write("S\n");
            println("cmd S");
         }
  }
  // IZ button clicked
     if (serial_port != null) {
       if (btn_serial_IZ.MouseIsOver()) {
          serial_port.write("IZ\n");
          println("cmd IZ");
       }  
  }
  // IX button clicked
     if (serial_port != null) {
       if (btn_serial_IX.MouseIsOver()) {
          serial_port.write("IX\n");
          println("cmd IX");
       }  
  }
  // > button clicked
     if (serial_port != null) {
       if (btn_serial_mrgt.MouseIsOver()) {
          serial_port.write("-X\n");
          println("cmd -X");
       }  
  }
  // < button clicked
     if (serial_port != null) {
       if (btn_serial_mlft.MouseIsOver()) {
          serial_port.write("+X\n");
          println("cmd +X");
       }  
  }
  // ^ button clicked
     if (serial_port != null) {
       if (btn_serial_mup.MouseIsOver()) {
          serial_port.write("+Z\n");
          println("cmd +Z");
       }  
  }
  // v button clicked
     if (serial_port != null) {
       if (btn_serial_mdn.MouseIsOver()) {
          serial_port.write("-Z\n");
          println("cmd -Z");
       }  
  }
  
}

void serialEvent(Serial p) {
  if (serial_port != null) {
    inString = p.readString();
 //   println(inString);       // debug info, no longer needed.
    serial_port.clear();  
    String[] q = split(inString, ":");
    inString = "";
//      println(q.length + " values found"); // debug info, no longer needed.
    switch(trim(q[0])) {
      case "X":
        posX = float(q[1]);
        println("X: ", posX);
        DrawTextBox("X: ", str(posX), 220, 170, 60, 60);
      break;
      case "Z":
        posZ = float(q[1]);
        println("Z: ", posZ);
        DrawTextBox("Z: ", str(posZ), 520, 170, 60, 60);
      break;
      case "IZ":
        if(q[1]=="OK") {
           println("IZ OK");
           btn_serial_IZ.Draw(#00FF00);
        } else {
           println("IZ failed");
           btn_serial_IZ.Draw(#FF0000);
        }
      break;
      default:
        println("Unrecognized signal");
      break;
     }
  }
}

void draw() {
  
  
  DrawPanelTitle("USB setup", 4,4,632,120);
  
  // draw the text box containing the selected serial port
  DrawTextBox("Select Port:", serial_list, 10, 36, 320, 60);
  // draw the buttons in the first panel
  btn_serial_up.Draw(218);
  btn_serial_dn.Draw(218);
  btn_serial_connect.Draw(218);
  btn_serial_disconnect.Draw(218);
  btn_serial_list_refresh.Draw(218);
  
  DrawPanelTitle("Initialize", 4,128,140,120);
  btn_serial_IX.Draw(218);
  btn_serial_IZ.Draw(218);

  DrawPanelTitle("Manual move (experts only !)", 148,128,488,120);
  btn_serial_STOP.Draw(#FF0000);
  btn_serial_mup.Draw(218);
  btn_serial_mdn.Draw(218);
  btn_serial_mrgt.Draw(218);
  btn_serial_mlft.Draw(218);
  
  DrawTextBox("X: ", str(posX), 220, 170, 60, 30);
  DrawTextBox("Z: ", str(posZ), 520, 170, 60, 30);
   
  DrawPanelTitle("Automated moves", 4,252,632,222);
  btn_proceed.Draw(#00FF00);

}


// function for drawing a panel with the title
void DrawPanelTitle(String title, int x, int y, int w, int h)
{
  fill(218);
  rect(x, y, w, h);
  fill(0);
  textAlign(CENTER);
  textSize(14);
  text(title, x + 10, y+10, w - 20, 28); 
}

// function for drawing a text box with title and contents
void DrawTextBox(String title, String str, int x, int y, int w, int h)
{
  fill(240);
  rect(x, y+16, w, h - 10);
  fill(64);
  textAlign(LEFT);
  textSize(12);
  text(title, x + 10, y, w - 20, h - 10);
  textSize(12);  
  text(str, x + 10, y + 20, w - 20, h - 10);
}

// button class used for all buttons
class Button {
  String label;
  float x;    // top left corner x position
  float y;    // top left corner y position
  float w;    // width of button
  float h;    // height of button
  
  // constructor
  Button(String labelB, float xpos, float ypos, float widthB, float heightB) {
    label = labelB;
    x = xpos;
    y = ypos;
    w = widthB;
    h = heightB;
  }
  
  // draw the button in the window
  void Draw(int ink) {
    fill(ink);
    stroke(0);
    rect(x, y, w, h, 10);
    textAlign(CENTER, CENTER);
    fill(0);
    text(label, x + (w / 2), y + (h / 2));
  }
  
  // returns true if the mouse cursor is over the button
  boolean MouseIsOver() {
    if (mouseX > x && mouseX < (x + w) && mouseY > y && mouseY < (y + h)) {
      return true;
    }
    return false;
  }
}

void actionPerformed(GUIEvent e) {
  if (e.getMessage().equals("Completed")) {
    println(tpause.getValue());
  }
}