import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.event.*;
import josx.rcxcomm.*;
import josx.vision.*;

public class RemoteControl implements ColorListener {
  static private JPanel arrowPanel = new JPanel();
  static private JPanel tiltPanel = new JPanel();
  static private JPanel colorPanel1;  
  static private JPanel colorPanel2;
  static private JPanel colorPanel3;
  static JIconButton upButton = new JIconButton("up.gif");
  static JIconButton downButton = new JIconButton("down.gif");
  static JIconButton stopButton = new JIconButton("stop.gif");
  static JIconButton leftButton = new JIconButton("left.gif");
  static JIconButton rightButton = new JIconButton("right.gif");
  static JIconButton tiltUpButton = new JIconButton("up.gif");
  static JIconButton tiltDownButton = new JIconButton("down.gif");

   
  static boolean client = false;
  static boolean connect = false;
  static String host = null;
  static ServerClass Server;

  public static class ServerClass extends Thread {
      Socket s = null;
      ObjectInputStream ois = null;
	  ObjectOutputStream oos = null;

      public ServerClass() {
        start();
	  }

	  public void run() {
		 try{
			if (!connect) {
			  System.out.println("ACTING AS SERVER.  WAITING FOR CONNECTION.");
			  ServerSocket ss = new ServerSocket(1234);
		      s = ss.accept();
			} else {
			  System.out.println("ATTEMPTING TO CONNECT TO:"+host);
              s = new Socket(host,1234);
		    }
            if (!client) {
				ois = new ObjectInputStream(s.getInputStream());
				while(true) {
					int r = ois.readInt();
					System.out.println("RECIEVED COMMAND:"+r);
					if (r == 1) {
                      downButton.doClick();
					} else if (r == 2) {
                      upButton.doClick();
					} else if (r == 3) {
                      stopButton.doClick();
					} else if (r == 4) {
                      leftButton.doClick();
					} else if (r == 5) {
                      rightButton.doClick();
					} else if (r == 6) {
                      tiltUpButton.doClick();
					} else if (r == 7) {
                      tiltDownButton.doClick();
				    }
				}
            } else {
               oos = new ObjectOutputStream(s.getOutputStream());
			}
		 } catch (Exception e) {
			 e.printStackTrace();
		 }
	  }

	  public void downButton() {
	    try {
			oos.writeInt(1);
			oos.flush();
	    } catch (Exception e) {
			e.printStackTrace();
	    }
	  }
	  public void upButton() {
	    try {
			oos.writeInt(2);
			oos.flush();
	    } catch (Exception e) {
			e.printStackTrace();
	    }
	  }
	  public void stopButton() {
	    try {
			oos.writeInt(3);
			oos.flush();
	    } catch (Exception e) {
			e.printStackTrace();
	    }
	  }
	  public void leftButton() {
	    try {
			oos.writeInt(4);
			oos.flush();
	    } catch (Exception e) {
			e.printStackTrace();
	    }
	  }
	  public void rightButton() {
	    try {
			oos.writeInt(5);
			oos.flush();
	    } catch (Exception e) {
			e.printStackTrace();
	    }
	  }
	  public void tiltUpButton() {
	    try {
			oos.writeInt(6);
			oos.flush();
	    } catch (Exception e) {
			e.printStackTrace();
	    }
	  }
	  public void tiltDownButton() {
	    try {
			oos.writeInt(7);
			oos.flush();
	    } catch (Exception e) {
			e.printStackTrace();
	    }
	  }
  };

  public RemoteControl() {

    // Create the Icon buttons
    // Set up the arrow panel including all the button action listeners

    arrowPanel.setBackground(Color.blue);
    arrowPanel.setLayout(new BorderLayout());

    upButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
		if (!client) {
          RCX.forward();
          RCX.playTone((short) 500, (byte) 100);
		} else {
		  Server.upButton();
		}
      }
    });
    arrowPanel.add(labelledComponent("Forwards",upButton, true), BorderLayout.NORTH);

    downButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
		if (!client) {
          RCX.backward();
          RCX.playTone((short) 1000,(byte) 100);
		} else {
		  Server.downButton();
		}
      }
    });
    arrowPanel.add(labelledComponent("Backwards",downButton, true), BorderLayout.SOUTH);   

    stopButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
		if (!client) {
          RCX.stop();
		} else {
		  Server.stopButton();
		}

      }
    });
    arrowPanel.add(labelledComponent("Stop",stopButton, true), BorderLayout.CENTER);

    leftButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
		if (!client){
          RCX.spinLeft();
		} else {
		  Server.leftButton();
		}

      }
    });
    arrowPanel.add(labelledComponent("Left",leftButton, true), BorderLayout.WEST);

    rightButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
		if (!client) {
          RCX.spinRight();
		} else {
		  Server.rightButton();
		}

      }
    });
    arrowPanel.add(labelledComponent("Right",rightButton, true), BorderLayout.EAST);

    // Set up the tilt and colors panel, including the tilt button action listeners

    tiltPanel.setBackground(Color.blue);
    tiltPanel.setLayout(new BorderLayout());

    tiltUpButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
		if (!client) {
          RCX.tiltUp(1);
		} else {
		  Server.tiltUpButton();
		}
      }
    });
    tiltPanel.add(labelledComponent("Tilt Camera up",tiltUpButton, true), BorderLayout.NORTH);

    tiltDownButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
		if (!client) {
          RCX.tiltDown(1);
		} else {
		  Server.tiltDownButton();
		}
      }
    });
    tiltPanel.add(labelledComponent("Tilt Camera down",tiltDownButton, true), BorderLayout.SOUTH);

    Box currentColors = Box.createHorizontalBox();
    colorPanel1 = colorPanel();
    colorPanel2 = colorPanel();
    colorPanel3 = colorPanel();

    currentColors.add(colorPanel1);
    currentColors.add(colorPanel2);
    currentColors.add(colorPanel3);

    JPanel colorPanel4 = colorPanel();
    colorPanel4.setBackground(new Color(red2));
    JPanel colorPanel5 = colorPanel();
    colorPanel5.setBackground(new Color(red1));
    JPanel colorPanel6 = colorPanel();
    colorPanel6.setBackground(new Color(red2));

    Box targetColors = Box.createHorizontalBox();    

    targetColors.add(colorPanel4);
    targetColors.add(colorPanel5);
    targetColors.add(colorPanel6);

    tiltPanel.add(labelledComponent("Target Colors", targetColors, true), BorderLayout.WEST);
    tiltPanel.add(labelledComponent("Average Colors", currentColors, true), BorderLayout.EAST);
  }

  // Create a Box containing a labelled component.
  // Apply the glue thickly.

  private Box labelledComponent(String label, Component comp, boolean horizontal) {
    Box labelBox = (horizontal ? Box.createHorizontalBox() : Box.createVerticalBox());
    labelBox.add(Box.createGlue());
    JLabel lab = new JLabel(label);
    lab.setForeground(Color.yellow);
    labelBox.add(lab);
    labelBox.add(Box.createGlue());
    Box spaceBox = (horizontal ? Box.createHorizontalBox() : Box.createVerticalBox());
    spaceBox.add(Box.createGlue());
    spaceBox.add(comp);
    spaceBox.add(Box.createGlue());
    Box compBox = (horizontal ? Box.createVerticalBox() : Box.createHorizontalBox());
    compBox.add(Box.createGlue());
    compBox.add(spaceBox);
    compBox.add(labelBox);
    return compBox;
  }

  // Create a panel that displays a color

  private JPanel colorPanel() {
    JPanel colorPanel = new JPanel();
    Border border = BorderFactory.createLineBorder(Color.red,2);
    colorPanel.setBorder(border);

    // Set a minimum width 

    colorPanel.add(new JLabel("        "));
    return colorPanel;
  }

  static private long lastPlay = 0;

  // Follow the red object and play a sound when it is straight ahead 

  public void colorDetected(int region, int color) {
    if ((System.currentTimeMillis() - lastPlay) > 2000) {
      lastPlay = System.currentTimeMillis();
      if (region == 2) {
        RCX.forward(1);
        Vision.playSound("../../../Effects/CarHorn.wav");
      } else if (region == 1) {
        System.out.println("Region 1");
        RCX.spinLeft(1);
      } else if (region == 3) {
        System.out.println("Region 3");
        RCX.spinRight(1);
      }
    }
  }

  private static final int red1 = 0xfe9878;
  private static final int red2 = 0xd88868;

  public static void main(String [] args) { 

    if (args.length >= 1) {
      client = "client".equals(args[0]);
	}
    if (args.length >= 2) {
      connect = "connect".equals(args[1]);
	}
    if (args.length >= 3) {
	  host = args[2];
	}

	Server = new ServerClass();
    // Create an instance of this class for listening

    RemoteControl listener = new RemoteControl(); 

	// Create 3 regions and set them to look for a red object
    // Looking for darker red at the edges as color is not as bright there
    if (false) {
      Vision.addRectRegion(1, 0, 50, 38, 60);
      Vision.addRectRegion(2, 40, 50, 40, 60);
      Vision.addRectRegion(3, 82, 50, 37, 60);
      Vision.addColorListener(1, listener, red2);
      Vision.addColorListener(2, listener, red1);
      Vision.addColorListener(3, listener, red2);

      // Create the viewer and set its title
      Vision.startViewer("Robot Remote Control");

      // Get the frame and add the remote control and color components

      Frame visionFrame = Vision.getFrame();
      visionFrame.add("West", arrowPanel);
      visionFrame.add("East", tiltPanel);
      visionFrame.pack();
      visionFrame.setVisible(true);
    // Continually update the current color panels
    // Quits when the window is shut down

      for(;;) {
        colorPanel1.setBackground(new Color(Vision.getAvgRGB(1)));
        colorPanel1.revalidate();
        colorPanel2.setBackground(new Color(Vision.getAvgRGB(2)));
        colorPanel2.revalidate();
        colorPanel3.setBackground(new Color(Vision.getAvgRGB(3)));
        colorPanel3.revalidate();

        // System.out.println("Color1 is " + Integer.toHexString(Vision.getAvgRGB(1)));
        // System.out.println("Color2 is " + Integer.toHexString(Vision.getAvgRGB(2)));
        // System.out.println("Color3 is " + Integer.toHexString(Vision.getAvgRGB(3)));

        try {
          Thread.sleep(500);
        } catch (InterruptedException ie) {}
      }
    } else {
      Frame visionFrame = new Frame();
      visionFrame.add("West", arrowPanel);
      visionFrame.add("East", tiltPanel);
      visionFrame.pack();
      visionFrame.setVisible(true);

	}
  }
}
