import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

/**
   The GUI part for the client
   @author Sugiharto Widjaja
   @version 09/21/02
*/
public class ClientPanel extends JPanel
{
   /**
      Construct the GUI components
      @param master the client frame
   */
   public ClientPanel(JFrame master)
   {
      this.master = master;
      setLayout(new BorderLayout());
      fText = new JTextArea(ROW,COL);
      fText.setEditable(false);
      JScrollPane pane = new JScrollPane(fText);
      connect = new JButton("Connect");
      disconnect = new JButton("Disconnect");
      send = new JButton("Send");
      quit = new JButton("Quit");
      disableDisconnect();
      disableSend();
      addButtonListener();
      JPanel pane1 = new JPanel();
      pane1.add(pane);
      JPanel pane2 = new JPanel();
      pane2.add(connect);
      pane2.add(disconnect);
      pane2.add(send);
      pane2.add(quit);
      add(pane1, BorderLayout.CENTER);
      add(pane2, BorderLayout.SOUTH);
   }

   /**
      Inform server on client's quit
   */
   public void informServerOnQuit()
   {
      if(timeClient != null)
         timeClient.sendMessage("Q");
      System.exit(0);
   }

   /**
      Inform server on client's disconnection
   */
   public void informServerOnDisconnect()
   {
      if(timeClient != null)
         timeClient.sendMessage("D");
   }

   /**
      Enable the connect button
   */
   public void enableConnect()
   {
      connect.setEnabled(true);
   }

   /**
      Enable the disconnect button
   */
   public void disableConnect()
   {
      connect.setEnabled(false);
   }

   /**
      Enable the disconnect button
   */
   public void enableDisconnect()
   {
      disconnect.setEnabled(true);
   }

   /**
      Disable the disconnect button
   */
   public void disableDisconnect()
   {
      disconnect.setEnabled(false);
   }

   /**
      Enable the send button
   */
   public void enableSend()
   {
      send.setEnabled(true);
   }

   /**
      Disable the send button
   */
   public void disableSend()
   {
      send.setEnabled(false);
   }

   /**
      Get the text area
      @return the text area
   */
   public JTextArea getMedia()
   {
      return fText;
   }

   /**
      Add an action listener to the connect, disconnect, send, and quit buttons
   */
   private void addButtonListener()
   {
      connect.addActionListener(new
         ActionListener()
         {
            public void actionPerformed(ActionEvent e)
            {
               if (connPanel == null)
                  connPanel = new ConnectPanel(master, ClientPanel.this, timeClient);
               connPanel.show();
            }
         });
      disconnect.addActionListener(new
         ActionListener()
         {
            public void actionPerformed(ActionEvent e)
            {
               informServerOnDisconnect();
               enableConnect();
               disableDisconnect();
               disableSend();
               fText.append("*** Disconnected from the server\n");
            }
         });
      send.addActionListener(new
         ActionListener()
         {
            public void actionPerformed(ActionEvent e)
            {
               if(qPanel == null)
                  qPanel = new QueryPanel(master, ClientPanel.this, getTimeClient());
               qPanel.show();
            }
         });
      quit.addActionListener(new
         ActionListener()
         {
            public void actionPerformed(ActionEvent e)
            {
               informServerOnQuit();
               fText.append("*** Disconnected from the server\n");
            }
         });
   }

   /**
      Set the timezone client
      @param tz the timezone client
   */
   public void setTimeClient(TimeZoneClient tz)
   {
      timeClient = tz;
   }

   /**
      Return the timezone client
      @return the timezone client
   */
   public TimeZoneClient getTimeClient()
   {
      return timeClient;
   }

   // Number of rows of the text area
   private static final int ROW = 40;
   // Number of columns of the text area
   private static final int COL = 60;
   // The text area
   private JTextArea fText;
   // The connect button
   private JButton connect;
   // The disconnect button
   private JButton disconnect;
   // The send button
   private JButton send;
   // The quit button
   private JButton quit;
   // The timezone client
   private TimeZoneClient timeClient;
   // The dialog box used to connect to server
   private JDialog connPanel;
   // The dialog box used to send queries to server
   private JDialog qPanel;
   // The client frame
   private JFrame master;
}

/**
   The dialog box used to connect to server
   @author Sugiharto Widjaja
   @version 09/21/02
*/
class ConnectPanel extends JDialog
{
   /**
      Construct the dialog box
      @param master the client frame
      @param pane the client panel
      @param tz the timezone client
   */
   public ConnectPanel(JFrame master, ClientPanel pane, TimeZoneClient tz)
   {
      super(master, "Connect Panel", false);
      panel = pane;
      timeClient = tz;
      setSize(WIDTH, HEIGHT);
      setComponents();
   }

   /**
      Create the components for the dialog box
   */
   private void setComponents()
   {
      setHorizontalComponents();
      setVerticalComponents();
      getContentPane().add(vbox, BorderLayout.CENTER);
      addOkButtonListener();
      addCancelButtonListener();
   }

   /**
      Create the horizontal part components
   */
   private void setHorizontalComponents()
   {
      box1 = Box.createHorizontalBox();
      box1.add(new JLabel("Host name: "));
      box1.add(Box.createHorizontalStrut(H_STRUT));
      box1.add(host = new JTextField(H_FIELD));
      box2 = Box.createHorizontalBox();
      box2.add(new JLabel("Port number: "));
      box2.add(Box.createHorizontalStrut(H_STRUT));
      box2.add(port = new JTextField("", P_FIELD));
      box3 = Box.createHorizontalBox();
      box3.add(ok = new JButton("Ok"));
      box3.add(Box.createHorizontalStrut(H_STRUT));
      box3.add(cancel = new JButton("Cancel"));
   }

   /**
      Create the vertical part components
   */
   private void setVerticalComponents()
   {
      vbox = Box.createVerticalBox();
      vbox.add(box1);
      vbox.add(Box.createVerticalStrut(V_STRUT));
      vbox.add(box2);
      vbox.add(Box.createVerticalStrut(V_STRUT));
      vbox.add(box3);
   }

   /**
      Add the listener to ok button
   */
   private void addOkButtonListener()
   {
      ok.addActionListener(new
         ActionListener()
         {
            public void actionPerformed(ActionEvent e)
            {
               if(!errorFound())
               {
                  timeClient = new TimeZoneClient(hostName, portNum, panel);
                  if(timeClient.connectToServer())
                  {
                     panel.disableConnect();
                     panel.enableDisconnect();
                     panel.enableSend();
                     panel.setTimeClient(timeClient);
                  }
                  else
                     timeClient = null;
                  ConnectPanel.this.setVisible(false);
               }
            }
         });
   }

   /**
      Add the listener to cancel button
   */
   private void addCancelButtonListener()
   {
      cancel.addActionListener(new
         ActionListener()
         {
            public void actionPerformed(ActionEvent e)
            {
               ConnectPanel.this.setVisible(false);
            }
         });
   }

   /**
      Check whether client has inputted the correct hostname and port number
      @return true if client has inputted incorrect hostname or port number,
         false otherwise
   */
   private boolean errorFound()
   {
      hostName = host.getText();
      if(hostName.equals("") || !isValidPortNumber())
      {
         JOptionPane.showMessageDialog(panel,
            "Either your host name of your port number is invalid!",
            "Error!!", JOptionPane.ERROR_MESSAGE);
         return true;
      }
      else
         return false;
   }

   /**
      Check whether the inputted port number is a valid one
      @return true if it is valid, false otherwise
   */
   private boolean isValidPortNumber()
   {
      try
      {
         portNum = Integer.parseInt(port.getText());
         return true;
      }
      catch(NumberFormatException e)
      {
         return false;
      }
   }

   // The size of the text field for hostname
   private static final int H_FIELD = 12;
   // The size of the text field for port number
   private static final int P_FIELD = 11;
   // The width of the dialog box
   private static final int WIDTH = 280;
   // The height of the dialog box
   private static final int HEIGHT = 120;
   // The width of the invisible components
   private static final int H_STRUT = 35;
   // The height of the invisible components
   private static final int V_STRUT = 12;
   // The client panel
   private ClientPanel panel;
   // The timezone client
   private TimeZoneClient timeClient;
   // The hostname of the server
   private String hostName;
   // The port number of server
   private int portNum;
   // The text field for hostname
   private JTextField host;
   // The text field for port number
   private JTextField port;
   // The ok button
   private JButton ok;
   // The cancel button
   private JButton cancel;
   // The horizontal box for hostname
   private Box box1;
   // The horizontal box for port number
   private Box box2;
   // The horizontal boxs for ok and cancel buttons
   private Box box3;
   // The vertical box
   private Box vbox;
}

/**
   The query panel to send queries to server
   @author Sugiharto Widjaja
   @version 09/21/02
*/
class QueryPanel extends JDialog
{
   /**
      Construct the dialog box to send queries to server
      @param master the client frame
      @param pane the client panel
      @param tz the timezone client
   */
   public QueryPanel(JFrame master, ClientPanel pane, TimeZoneClient tz)
   {
      super(master, "Connect Panel", false);
      timeClient = tz;
      this.pane = pane;
      setSize(WIDTH, HEIGHT);
      setComponents();
   }

   /**
      Set the GUI components
   */
   private void setComponents()
   {
      setComboBox();
      setHorizontalComponent();
      setVerticalComponent();
      getContentPane().add(vbox, BorderLayout.CENTER);
      addOkButtonListener();
      addCancelButtonListener();
      addResetButtonListener();
   }

   /**
      Set the combo boxes that contains the cities selection
   */
   private void setComboBox()
   {
      myCityComboBox = new JComboBox();
      myCityComboBox.setEditable(true);
      myCityComboBox.addItem("San Jose");
      myCityComboBox.addItem("Dhaka");
      myCityComboBox.addItem("Dubai");
      myCityComboBox.addItem("Jakarta");
      myCityComboBox.addItem("Seoul");
      myCityComboBox.addItem("Singapore");
      destCityComboBox = new JComboBox();
      destCityComboBox.setEditable(true);
      destCityComboBox.addItem("San Jose");
      destCityComboBox.addItem("Dhaka");
      destCityComboBox.addItem("Dubai");
      destCityComboBox.addItem("Jakarta");
      destCityComboBox.addItem("Seoul");
      destCityComboBox.addItem("Singapore");
   }

   /**
      Set the horizontal components of the GUI
   */
   private void setHorizontalComponent()
   {
      box1 = Box.createHorizontalBox();
      box1.add(new JLabel("My city: "));
      box1.add(Box.createHorizontalStrut(H_STRUT));
      box1.add(myCityComboBox);
      box2 = Box.createHorizontalBox();
      box2.add(new JLabel("Dest city: "));
      box2.add(Box.createHorizontalStrut(H_STRUT));
      box2.add(destCityComboBox);
      box3 = Box.createHorizontalBox();
      box3.add(new JLabel("Date: (yyyy/mm/dd) "));
      box3.add(Box.createHorizontalStrut(H_STRUT));
      box3.add(year = new JTextField(4));
      box3.add(Box.createHorizontalStrut(H_STRUT));
      box3.add(month = new JTextField(2));
      box3.add(Box.createHorizontalStrut(H_STRUT));
      box3.add(day = new JTextField(2));
      box4 = Box.createHorizontalBox();
      box4.add(new JLabel("Time: (hh:mm) "));
      box4.add(Box.createHorizontalStrut(H_STRUT));
      box4.add(hour = new JTextField(2));
      box4.add(Box.createHorizontalStrut(H_STRUT));
      box4.add(minute = new JTextField(2));
      box5 = Box.createHorizontalBox();
      box5.add(okButton = new JButton("Ok"));
      box5.add(Box.createHorizontalStrut(H_STRUT));
      box5.add(cancelButton = new JButton("Cancel"));
      box5.add(Box.createHorizontalStrut(H_STRUT));
      box5.add(resetButton = new JButton("Reset"));
   }

   /**
      Set the vertical component of the GUI
   */
   private void setVerticalComponent()
   {
      vbox = Box.createVerticalBox();
      vbox.add(box1);
      vbox.add(Box.createVerticalStrut(V_STRUT));
      vbox.add(box2);
      vbox.add(Box.createVerticalStrut(V_STRUT));
      vbox.add(box3);
      vbox.add(Box.createVerticalStrut(V_STRUT));
      vbox.add(box4);
      vbox.add(Box.createVerticalStrut(V_STRUT));
      vbox.add(box5);
   }

   /**
      Add the listener to the ok button
   */
   private void addOkButtonListener()
   {
      okButton.addActionListener(new
         ActionListener()
         {
            public void actionPerformed(ActionEvent e)
            {
               if(!errorFound())
               {
                  String date = year.getText() + "-" + month.getText() + "-" + day.getText();
                  String time = hour.getText() + ":" + minute.getText();
                  timeClient.sendMessage("R>" + (String) myCityComboBox.getSelectedItem() + ";" +
                                         date + ";" + time + ";" +
                                         (String) destCityComboBox.getSelectedItem());
                  QueryPanel.this.setVisible(false);
               }
               else
                  JOptionPane.showMessageDialog(pane,
                              "Make sure you fill every information!",
                              "Error!!", JOptionPane.ERROR_MESSAGE);
            }
         });
   }

   /**
      Check whether client has filled out all the required inputs
      @return true if client doesn't fill all the required inputs,
         false otherwise
   */
   private boolean errorFound()
   {
      if(month.getText().equals("") || day.getText().equals("") || year.getText().equals("")
         || hour.getText().equals("") || minute.getText().equals(""))
         return true;
      else
         return false;
   }

   /**
      Add the listener to cancel button
   */
   private void addCancelButtonListener()
   {
      cancelButton.addActionListener(new
         ActionListener()
         {
            public void actionPerformed(ActionEvent e)
            {
               QueryPanel.this.setVisible(false);
            }
         });
   }

   /**
      Add the listener to reset button
   */
   private void addResetButtonListener()
   {
      resetButton.addActionListener(new
         ActionListener()
         {
            public void actionPerformed(ActionEvent e)
            {
               month.setText("");
               day.setText("");
               year.setText("");
               hour.setText("");
               minute.setText("");
            }
         });
   }

   // The width of the dialog box
   private static final int WIDTH = 300;
   // The height of the dialog box
   private static final int HEIGHT = 200;
   // The width of the invisible component
   private static final int H_STRUT = 35;
   // The height of the invisible component
   private static final int V_STRUT = 12;
   // The timezone clinet
   private TimeZoneClient timeClient;
   // The combo box for original city
   private JComboBox myCityComboBox;
   // The combo box for destination city
   private JComboBox destCityComboBox;
   // The box for the the original city combo box
   private Box box1;
   // The box for the destination city combo box
   private Box box2;
   // The box for the date
   private Box box3;
   // The box for the time
   private Box box4;
   // The box for the Ok, cancel, and reset buttons
   private Box box5;
   // The vertical box
   private Box vbox;
   // The text field for month
   private JTextField month;
   // The text field for day
   private JTextField day;
   // The text field for year
   private JTextField year;
   // The text field for hour
   private JTextField hour;
   // The text field for minute
   private JTextField minute;
   // The ok button
   private JButton okButton;
   // The cancel button
   private JButton cancelButton;
   // The reset button
   private JButton resetButton;
   // The client panel
   private ClientPanel pane;
}
