import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import state.*;
import control.*;
import nddsJava.*;

class NomadFrame extends JFrame {
  Container contentPane;
  NomadDesktopPane deskpane;
  nddsTelemetryThread ndds;
  
  JPanel statusArea = new JPanel();
  JLabel status = new JLabel("");
  statusListener listener = new statusListener(this);

  RSPFrame RSP;
  RCPFrame RCP;
  JInternalFrame SAP;
    
  NomadFrame(String title) {
    super(title);
    
    setBounds(100, 100, 1000, 740);
    
    contentPane = getContentPane();
    deskpane = new NomadDesktopPane();
    
    setJMenuBar(createMenuBar());

    statusArea.setBorder(BorderFactory.createRaisedBevelBorder());
    statusArea.setLayout(new FlowLayout(FlowLayout.LEFT,0,0));
    statusArea.add(status);
    status.setHorizontalAlignment(JLabel.LEFT);
    showStatus(" ");
    
    contentPane.add(deskpane, BorderLayout.CENTER);
    contentPane.add(statusArea, BorderLayout.SOUTH);

    RSP = new RSPFrame("Robot State", false, true, true, true);
    RSP.setBounds(0, 0, 820, 575);
    deskpane.add(RSP);

    RCP = new RCPFrame("Robot Control", false, true, true, true);
    RCP.setBounds(40, 40, 820, 575);
    deskpane.add(RCP);

    //SAP = new JInternalFrame("Science Autonomy", true, true, true, true);
    //SAP.setBounds(80, 80, 820, 575);
    //deskpane.add(SAP);
  }

  void setNdds(nddsTelemetryThread t) { ndds = t; }

  private JMenuBar createMenuBar() {
    JMenuBar mb = new JMenuBar();

    JMenu fileMenu = new JMenu("File");
    JMenuItem exitItem = new JMenuItem("Exit", 'x');
    
    JMenu windowMenu = new JMenu("Window");
    JMenu newWinMenu = new JMenu("New...");
    JMenuItem rspItem = new JMenuItem("Robot State", 'S');
    JMenuItem rcpItem = new JMenuItem("Robot Control", 'C');
    JMenuItem sapItem = new JMenuItem("Science Autonomy", 'A');
    JMenuItem cascadeItem = new JMenuItem("Cascade", 'C');
    JMenuItem miniAllItem = new JMenuItem("Minimize All", 'M');
    JMenuItem openAllItem = new JMenuItem("Open All", 'O');

    JMenu testMenu = new JMenu("Test");
    JMenu testRobotMenu = new JMenu("Robot");
    JMenuItem linksItem = new JMenuItem("Links", 'L');
    JMenuItem armItem = new JMenuItem("Arm", 'A');
    JMenuItem bogieItem = new JMenuItem("Bogies", 'B');
    JMenuItem cameraItem = new JMenuItem("Camera", 'C');
    JMenu testPositionMenu = new JMenu("Positions");
    JMenuItem rpItem = new JMenuItem("Roll/Pitch", 'R');
    JMenuItem speedItem = new JMenuItem("Speed", 'S');
    JMenuItem headingItem = new JMenuItem("Heading", 'H');
    JMenuItem gpsItem = new JMenuItem("GPS", 'G');
    JMenu testVitalsMenu = new JMenu("Vitals");
    JMenuItem wheelsItem = new JMenuItem("Wheels", 'W');
    JMenu testWeatherMenu = new JMenu("Weather");
    JMenuItem TempItem = new JMenuItem("Temperature", 'T');
    JMenuItem PressItem = new JMenuItem("Pressure", 'P');

    fileMenu.add(exitItem);

    windowMenu.add(newWinMenu);
    newWinMenu.add(rspItem);
    newWinMenu.add(rcpItem);
    newWinMenu.add(sapItem);
    windowMenu.addSeparator();
    windowMenu.add(cascadeItem);
    windowMenu.add(miniAllItem);
    windowMenu.add(openAllItem);
    
    testMenu.add(testRobotMenu);
    testMenu.add(testPositionMenu);
    testMenu.add(testVitalsMenu);
    testMenu.add(testWeatherMenu);
    testRobotMenu.add(linksItem);
    testRobotMenu.add(armItem);
    testRobotMenu.add(bogieItem);
    testRobotMenu.add(cameraItem);
    testPositionMenu.add(rpItem);
    testPositionMenu.add(speedItem);
    testPositionMenu.add(headingItem);
    testPositionMenu.add(gpsItem);
    testVitalsMenu.add(wheelsItem);
    testWeatherMenu.add(TempItem);
    testWeatherMenu.add(PressItem);

    exitItem.setActionCommand("Exit the Nomad Interface");
    rspItem.setActionCommand("Open a new Robot State Window");
    rcpItem.setActionCommand("Open a new Robot Control Window");
    sapItem.setActionCommand("Open a new Science Autonomy Window");
    cascadeItem.setActionCommand("Cascade all Open Windows");
    miniAllItem.setActionCommand("Minimize all Open Windows");
    openAllItem.setActionCommand("Open all Minimzed Windows");
    linksItem.setActionCommand("Test Links (Deploy/Stow Once)");
    armItem.setActionCommand("Test Arm (Theta 0->120, Phi 0->180, Alpha 10->170)");
    bogieItem.setActionCommand("Test Bogie Angles (0 -> 20 -> -20 -> 0)");
    cameraItem.setActionCommand("Test Pan, Tilt, and Field of View of Hi-res camera");
    rpItem.setActionCommand("Test Roll/Pitch (Pitch, Roll, Pitch & Roll)");
    speedItem.setActionCommand("Test Speed (0 -> 50 -> -50 -> 0)");
    headingItem.setActionCommand("Test Heading (N, E, S, W, Circle)");
    gpsItem.setActionCommand("Test GPS (up, right, down, left)");
    wheelsItem.setActionCommand("Test Wheel Speeds and Amps");
    TempItem.setActionCommand("Test Internal Temperature");
    TempItem.setActionCommand("Test Pressure");

    exitItem.addChangeListener(listener);
    rspItem.addChangeListener(listener);
    rcpItem.addChangeListener(listener);
    sapItem.addChangeListener(listener);
    cascadeItem.addChangeListener(listener);
    miniAllItem.addChangeListener(listener);
    openAllItem.addChangeListener(listener);
    linksItem.addChangeListener(listener);
    armItem.addChangeListener(listener);
    bogieItem.addChangeListener(listener);
    cameraItem.addChangeListener(listener);
    rpItem.addChangeListener(listener);
    speedItem.addChangeListener(listener);
    headingItem.addChangeListener(listener);
    gpsItem.addChangeListener(listener);
    wheelsItem.addChangeListener(listener);
    TempItem.addChangeListener(listener);
    PressItem.addChangeListener(listener);
    
    fileMenu.setMnemonic('F');
    windowMenu.setMnemonic('W');
    newWinMenu.setMnemonic('N');
    testMenu.setMnemonic('T');
    testRobotMenu.setMnemonic('R');
    testPositionMenu.setMnemonic('P');
    testVitalsMenu.setMnemonic('V');
    testWeatherMenu.setMnemonic('W');
    
    mb.add(fileMenu);
    mb.add(windowMenu);
    mb.add(testMenu);

    exitItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	if (ndds != null)
	  ndds.disconnect();  // disconnect from telemetry, if connected
	System.exit(0);       // exit program
      }
    });
    
    rspItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
 	if (RSP.isClosed()) { // RSP is closed
 	  RSP = new RSPFrame("Robot State", false, true, true, true);
 	  RSP.setBounds(0, 0, 820, 575);
 	  deskpane.add(RSP);
 	  return;
 	} else {              // already a RSP panel around
 	JOptionPane.showMessageDialog(NomadFrame.this,
 				      "A Robot State window already exists.",
 				      "Window Exists",
 				      JOptionPane.INFORMATION_MESSAGE);
	}
      }
    });
    
    rcpItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	if (RCP.isClosed()) { // no existing RCP
	  RCP = new RCPFrame("Robot Control", false, true, true, true);
	  RCP.setBounds(0, 0, 820, 575);
	  deskpane.add(RCP);
	  return;
	} else {              // already a RCP panel around
	JOptionPane.showMessageDialog(NomadFrame.this,
				      "A Robot Control window already exists.",
				      "Window Exists",
				      JOptionPane.INFORMATION_MESSAGE);
        }
      }
    });
    
//     sapItem.addActionListener(new ActionListener() {
//       public void actionPerformed(ActionEvent e) {
// 	if (SAP.isClosed()) { // no existing SAP
// 	  //SAP = new SAPFrame("Science Autonomy", false, true, true, true);
// 	  //SAP.setBounds(0, 0, 820, 575);
// 	  //deskpane.add(SAP);
// 	  return;
// 	} else {              // already a SAP panel around
// 	JOptionPane.showMessageDialog(NomadFrame.this,
// 				      "A Science Autonomy window "+
// 				      "already exists.",
// 				      "Window Exists",
// 				      JOptionPane.INFORMATION_MESSAGE);
//         }
//       }
//     });
    
    cascadeItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	deskpane.cascade();
      }
    });
    
    miniAllItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	deskpane.minimizeAll();
      }
    });
    
    openAllItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	deskpane.openAll();
      }
    });

    // Test functions
    
    linksItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	synchronized(RSP) {
	  linkTestThread t = new linkTestThread(RSP);
	  t.start();
	}
      }
    });

    armItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	synchronized(RSP) {
	  armTestThread t = new armTestThread(RSP);
	  t.start();
	}
      }
    });

    bogieItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	synchronized(RSP) {
	  bogieTestThread t = new bogieTestThread(RSP);
	  t.start();
	}
      }
    });

    cameraItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	synchronized(RSP) {
	  fovTestThread t = new fovTestThread(RSP);
	  t.start();
	}
      }
    });

    rpItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	synchronized(RSP) {
	  rpTestThread t = new rpTestThread(RSP);
	  t.start();
	}
      }
    });

    speedItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	synchronized(RSP) {
	  speedTestThread t = new speedTestThread(RSP);
	  t.start();
	}
      }
    });

    headingItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	synchronized(RSP) {
	  headingTestThread t = new headingTestThread(RSP);
	  t.start();
	}
      }
    });

    gpsItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	synchronized(RSP) {
	  gpsTestThread t = new gpsTestThread(RSP);
	  t.start();
	}
      }
    });

    wheelsItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	synchronized(RSP) {
	  wheelTestThread t = new wheelTestThread(RSP);
	  t.start();
	}
      }
    });
    
    TempItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	synchronized(RSP) {
	  TempTestThread t = new TempTestThread(RSP);
	  t.start();
	}
      }
    });
    
    PressItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	synchronized(RSP) {
	  pressureTestThread t = new pressureTestThread(RSP);
	  t.start();
	}
      }
    });
    
    return mb;
  }

  public void showStatus(String s) {
    status.setText(s);
  }

  // update functions for telemetry
  synchronized public void setRoll(double r) { RSP.setRoll(r); }
  synchronized public void setPitch(double p) { RSP.setPitch(p); }
  synchronized public void setRobotSpeed(int speed)
    { RSP.setRobotSpeed(speed); }
  synchronized public void setRadius(int rad) { RSP.setRadius(rad); }
  synchronized public void setHeading(int h) { RSP.setHeading(h); }
  synchronized public void setTheta(double t) { RSP.setTheta(t); }
  synchronized public void setPhi(double p) { RSP.setPhi(p); }
  synchronized public void setAlpha(double a) { RSP.setAlpha(a); }
  synchronized public void setBogie(double b) { RSP.setBogie(b); }
  synchronized public void setLinks(double gr, double gl)
    { RSP.setLinks(gr, gl); }
  synchronized public void setWheelSpeed(int ur, int ul, int lr, int ll)
    { RSP.setWheelSpeed(ur, ul, lr, ll); }
  synchronized public void setAmps(boolean ure, boolean ule, boolean lre,
				   boolean lle, boolean sre, boolean sle,
				   boolean urf, boolean ulf, boolean lrf,
				   boolean llf, boolean srf, boolean slf) {
    RSP.setAmps(ure, ule, lre, lle, sre, sle, urf, ulf, lrf, llf, srf, slf); }
  synchronized public void setTemp(int i, int o) { RSP.setTemp(i,o); }
  synchronized public void setGPS(double x, double y, double z)
    { RSP.setGPS(x,y,z); }
  synchronized public void setPressure(int p) { RSP.setPressure(p); }
  synchronized public void setWind(short s, short g, int c, short d)
    { RSP.setWind(s,g,c,d); }
  synchronized public void setOdometer(long dist) { RSP.setOdometer(dist); }
  synchronized public void setTime(long t) { RSP.setTime(t); }
  synchronized public void setDriveMode(int m) { RSP.setDriveMode(m); }
  synchronized public void setCurrents(int c[], int m[], int s[])
    { RSP.setCurrents(c, m, s); }
  synchronized public void setMotors(int p[], int s[]) { RSP.setMotors(p, s); }
  synchronized public void setFOV(double p, double t, double f)
    { RSP.setFOV(p,t,f); }
}

class statusListener implements ChangeListener {
  NomadFrame nframe;

  public statusListener(NomadFrame n) {
    nframe = n;
  }

  public void stateChanged(ChangeEvent e) {
    JMenuItem b = (JMenuItem)e.getSource();
    if (b.isArmed())
      nframe.showStatus(b.getActionCommand());
  }
}
