import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;

/**
 * A class that represents GUIs for inserting, modifying, deleting
 * and selecting customers from a customer collection.
 * @author Derek Bridge
 */
public class CustomerGUI
   extends JFrame
   implements ICDGUI
{
/* =======================================================================
       CONSTRUCTORS
   =======================================================================
*/

   /**
    * Allocates a new customer GUI object for a specified collection of
    * customers.
    *
    * @param theParent the component that launched this GUI.
    * @param theCustCollection the collection of customers.
    * @param theCDCollection the collection of CDs.
    */
   public CustomerGUI(ICDGUI theParent, 
      CustomerCollection theCustCollection, CDCollection theCDCollection)
   {  super("CD-Direkt Customers");
      parentComp = theParent;
      custCollection = theCustCollection;
      cdCollection = theCDCollection;
      JPanel searchPanel = createSearchPanel();
      JPanel customerPanel = createCustomerPanel();
      JPanel returnPanel = createReturnPanel();
      Container contentPane = getContentPane();
      contentPane.setLayout(new BorderLayout());
      contentPane.add(searchPanel, BorderLayout.WEST);
      contentPane.add(customerPanel, BorderLayout.EAST);
      contentPane.add(returnPanel, BorderLayout.SOUTH);
      setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
      pack();
   }

/* =======================================================================
       PUBLIC INTERFACE
   =======================================================================
*/

/* --Setters----------------------------------------------------------- */

   /**
    * Displays the current customer's details (if any) on the
    * customer panel.
    */
   public void displayCurrentCustomer()
   {  if (currentCustomer == null)
      {  idNumTF.setText("");
         nameTF.setText("");
         houseStreetTF.setText("");
         townCountyTF.setText("");
         teleNumTF.setText("");
      }
      else
      {  idNumTF.setText(currentCustomer.getIdNum());
         nameTF.setText(currentCustomer.getName());
         houseStreetTF.setText(currentCustomer.getHouseStreet());
         townCountyTF.setText(currentCustomer.getTownCounty());
         teleNumTF.setText(currentCustomer.getTeleNum());
      }
   }

   /**
    * Disables this GUI when the user goes to another GUI to look
    * at a customer's orders
    */
   public void disableGUI()
   {  newBtn.setEnabled(false);
      insertBtn.setEnabled(false);
      cancelBtn.setEnabled(false);
      modifyBtn.setEnabled(false);
      deleteBtn.setEnabled(false);
      ordersBtn.setEnabled(false);
      custList.setEnabled(false);
      nameTF.setEnabled(false);
      houseStreetTF.setEnabled(false);
      townCountyTF.setEnabled(false);
      teleNumTF.setEnabled(false);
      returnBtn.setEnabled(false);
   }

   /**
    * Enable this GUI when the user returns from another GUI where
    * s/he was looking at the customer's orders.
    */
   public void enableGUI()
   {  setGUIForCustomerViewing();
      returnBtn.setEnabled(true);
   }

   /**
    * If one GUI sends you to another GUI and that GUI wants to
    * supply a result, it does so using this setter. But customer GUIs
    * do nothing with any such result.
    *
    * @param anObj the result being supplied.
    */
   public void setResult(Object anObj)
   {
   }


/* =======================================================================
       HELPER METHODS
   =======================================================================
*/

   /**
    * Lays out a panel containing a list of current customers, and
    * offers search options.
    */
   private JPanel createSearchPanel()
   {  viewedCustomers = custCollection.findAll();
      custList = new JList(viewedCustomers);
      custList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      JScrollPane scrollPane = new JScrollPane(custList);
      JLabel idNumLbl = new JLabel("Customer number:");
      searchIdNumTF = new JTextField("", ID_TF_COLS);
      JLabel nameLbl = new JLabel("Customer name:");
      searchNameTF = new JTextField("", NAME_TF_COLS);
      searchBtn = new JButton(SEARCH);
      fullBtn = new JButton(FULL);

      custList.addListSelectionListener(new ListSelectionListener()
      {  public void valueChanged(ListSelectionEvent lse)
         {  if (lse.getValueIsAdjusting()) // mouse wasn't yet at rest
            {  // do nothing
            }
            if (custList.isSelectionEmpty()) // somehow, no selection was made
            {  // do nothing
            }
            else
            {  int index = custList.getSelectedIndex(); 
               currentCustomer = (Customer) viewedCustomers.elementAt(index);
               setGUIForCustomerViewing();
            }
          }
      });

      searchBtn.addActionListener(new ActionListener()
      {  public void actionPerformed(ActionEvent ae)
         {  String idNum = searchIdNumTF.getText().trim();
            String name = searchNameTF.getText().trim();
            if (! idNum.equals("") && name.equals("")) 
            {  viewedCustomers = custCollection.findById(idNum);
               custList.setListData(viewedCustomers);
               custList.setSelectedIndex(-1);
            }
            else if (idNum.equals("") && ! name.equals(""))
            {  viewedCustomers = custCollection.findByName(name);
               custList.setListData(viewedCustomers);
               custList.setSelectedIndex(-1);
            }
            else
            {  JOptionPane.showMessageDialog(null,
                  "To search, you must supply either a customer " +
                  "identification number or a customer name.",
                  "Error in search values",
                  JOptionPane.ERROR_MESSAGE);
            }
         }
      });

      fullBtnLstnr = new ActionListener()
      {  public void actionPerformed(ActionEvent ae)
         {  searchIdNumTF.setText("");
            searchNameTF.setText("");
            viewedCustomers = custCollection.findAll();
            custList.setListData(viewedCustomers);
            custList.setSelectedIndex(-1);
         }
      };
      fullBtn.addActionListener(fullBtnLstnr);

      JPanel p = new JPanel();
      GridBagLayout gbl = new GridBagLayout();
      GridBagConstraints gbc = new GridBagConstraints();
      p.setLayout(gbl);
      gbc.insets = new Insets(5, 5, 5, 0); 
      gbc.fill = GridBagConstraints.NONE;
      gbc.anchor = GridBagConstraints.CENTER;
      GuiUtility.addComp(scrollPane, p, gbl, gbc, 0, 0, 
         1, GridBagConstraints.REMAINDER, 0, 0);
      gbc.fill = GridBagConstraints.HORIZONTAL; 
      gbc.anchor = GridBagConstraints.WEST;
      GuiUtility.addComp(idNumLbl, p, gbl, gbc, 1, 0, 1, 1, 0, 0);
      GuiUtility.addComp(Box.createHorizontalStrut(10), p, gbl, gbc, 
         1, 1, 1, 1, 0, 0);
      GuiUtility.addComp(searchIdNumTF, p, gbl, gbc, 1, 2, 1, 1, 0, 0);
      GuiUtility.addComp(nameLbl, p, gbl, gbc, 2, 0, 1, 1, 0, 0);
      GuiUtility.addComp(Box.createHorizontalStrut(10), p, gbl, gbc, 
         2, 1, 1, 1, 0, 0);
      GuiUtility.addComp(searchNameTF, p, gbl, gbc, 2, 2, 1, 1, 0, 0);
      gbc.fill = GridBagConstraints.NONE;
      gbc.anchor = GridBagConstraints.CENTER;
      GuiUtility.addComp(searchBtn, p, gbl, gbc, 3, 0,
         1, GridBagConstraints.REMAINDER, 0, 0);
      GuiUtility.addComp(fullBtn, p, gbl, gbc, 4, 0,
         1, GridBagConstraints.REMAINDER, 0, 0);
      return p;
   }

   /**
    * Lays out a panel containing a selected customer's details, and
    * offers update options.
    */
   private JPanel createCustomerPanel()
   {  JLabel idNumLbl = new JLabel("Customer number:");
      idNumTF = new JTextField("", ID_TF_COLS);
      idNumTF.setEnabled(false);
      JLabel nameLbl = new JLabel("Customer name:");
      nameTF = new JTextField("", NAME_TF_COLS);
      JLabel addressLbl = new JLabel("Address:");
      houseStreetTF = new JTextField("", ADDRESS_TF_COLS);
      townCountyTF = new JTextField("", ADDRESS_TF_COLS);
      JLabel teleNumLbl = new JLabel("Tel:");
      teleNumTF = new JTextField("", TELE_TF_COLS);
      newBtn = new JButton(NEW);
      insertBtn = new JButton(INSERT);
      cancelBtn = new JButton(CANCEL);
      modifyBtn = new JButton(MODIFY);
      deleteBtn = new JButton(DELETE);
      ordersBtn = new JButton(ORDERS);
      setGUIForNoCustomerSelected();

      newBtn.addActionListener(new ActionListener()
      {  public void actionPerformed(ActionEvent ae)
         {  setGUIForCustomerEntry();
         }
      });

      insertBtn.addActionListener(new ActionListener()
      {  public void actionPerformed(ActionEvent ae)
         {  String name = nameTF.getText().trim();
            String houseStreet = houseStreetTF.getText().trim();
            String townCounty = townCountyTF.getText().trim();
            String teleNum = teleNumTF.getText().trim();
            if (name.equals("") || houseStreet.equals("") ||
                townCounty.equals(""))
            {  JOptionPane.showMessageDialog(null,
                  "You must supply a customer name and a full address.",
                  "Incomplete new customer data",
                  JOptionPane.ERROR_MESSAGE);
            }
            else
            {  currentCustomer = 
                  new Customer(name, houseStreet, townCounty, teleNum);
               custCollection.add(currentCustomer);
               setGUIForCustomerViewing();
               fullBtnLstnr.actionPerformed(new ActionEvent(
                  fullBtn, ActionEvent.ACTION_PERFORMED, FULL));
            }
         }
      });

      cancelBtn.addActionListener(new ActionListener()
      {  public void actionPerformed(ActionEvent ae)
         {  setGUIForNoCustomerSelected();
         }
      });

      modifyBtn.addActionListener(new ActionListener()
      {  public void actionPerformed(ActionEvent ae)
         {  String name = nameTF.getText().trim();
            String houseStreet = houseStreetTF.getText().trim();
            String townCounty = townCountyTF.getText().trim();
            String teleNum = teleNumTF.getText().trim();
            if (name.equals("") || houseStreet.equals("") ||
                townCounty.equals(""))
            {  JOptionPane.showMessageDialog(null,
                  "The customer name and address cannot be blank.",
                  "Trying to make fields blank",
                  JOptionPane.ERROR_MESSAGE);
            }
            else
            {  currentCustomer.setName(name);
               currentCustomer.setHouseStreet(houseStreet);
               currentCustomer.setTownCounty(townCounty);
               currentCustomer.setTeleNum(teleNum);
               setGUIForCustomerViewing();
               fullBtnLstnr.actionPerformed(new ActionEvent(
                  fullBtn, ActionEvent.ACTION_PERFORMED, FULL));
            }
         }
      });     

      deleteBtn.addActionListener(new ActionListener()
      {  public void actionPerformed(ActionEvent ae)
         {  int confirm = JOptionPane.showConfirmDialog(null,
               "This will permanently delete this customer. Are you sure?",
               "Confirm or cancel deletion",
               JOptionPane.YES_NO_OPTION);
            if (confirm == JOptionPane.YES_OPTION)
            {  custCollection.remove(currentCustomer);
               setGUIForNoCustomerSelected();
               fullBtnLstnr.actionPerformed(new ActionEvent(
                  fullBtn, ActionEvent.ACTION_PERFORMED, FULL));
            }
         }
      }); 

      ordersBtn.addActionListener(new ActionListener()
      {  public void actionPerformed(ActionEvent ae)
         {  disableGUI();
            OrderGUI orderGUI = new OrderGUI(
               CustomerGUI.this, currentCustomer, new OrderCollection(
               currentCustomer.getCurrentOrders()), cdCollection);
            orderGUI.setVisible(true);
         }
      });
               
      JPanel p = new JPanel();
      GridBagLayout gbl = new GridBagLayout();
      GridBagConstraints gbc = new GridBagConstraints();
      p.setLayout(gbl);
      gbc.insets = new Insets(5, 5, 5, 0); 
      gbc.fill = GridBagConstraints.HORIZONTAL; 
      gbc.anchor = GridBagConstraints.WEST;
      GuiUtility.addComp(idNumLbl, p, gbl, gbc, 0, 0, 1, 1, 0, 0);
      GuiUtility.addComp(Box.createHorizontalStrut(10), p, gbl, gbc, 
         0, 1, 1, 1, 0, 0);
      GuiUtility.addComp(idNumTF, p, gbl, gbc, 
         0, 2, 1, GridBagConstraints.REMAINDER, 0, 0);
      GuiUtility.addComp(nameLbl, p, gbl, gbc, 1, 0, 1, 1, 0, 0);
      GuiUtility.addComp(Box.createHorizontalStrut(10), p, gbl, gbc, 
         1, 1, 1, 1, 0, 0);
      GuiUtility.addComp(nameTF, p, gbl, gbc, 
         1, 2, 1, GridBagConstraints.REMAINDER, 0, 0);
      GuiUtility.addComp(addressLbl, p, gbl, gbc, 2, 0, 1, 1, 0, 0);
      GuiUtility.addComp(Box.createHorizontalStrut(10), p, gbl, gbc, 
         2, 1, 1, 1, 0, 0);
      GuiUtility.addComp(houseStreetTF, p, gbl, gbc, 
         2, 2, 1, GridBagConstraints.REMAINDER, 0, 0);
      GuiUtility.addComp(townCountyTF, p, gbl, gbc, 3, 2, 1, 1, 0, 0);
      GuiUtility.addComp(Box.createHorizontalStrut(10), p, gbl, gbc, 
         3, 3, 1, 1, 0, 0);
      GuiUtility.addComp(teleNumLbl, p, gbl, gbc, 3, 4, 1, 1, 0, 0);
      GuiUtility.addComp(Box.createHorizontalStrut(10), p, gbl, gbc, 
         3, 5, 1, 1, 0, 0);
      GuiUtility.addComp(teleNumTF, p, gbl, gbc, 
         3, 6, 1, GridBagConstraints.REMAINDER, 0, 0);
      gbc.fill = GridBagConstraints.NONE;
      gbc.anchor = GridBagConstraints.CENTER;
      JPanel btnPnl1 = new JPanel();
      btnPnl1.setLayout(new BoxLayout(btnPnl1, BoxLayout.X_AXIS));
      btnPnl1.add(newBtn);
      btnPnl1.add(insertBtn);
      btnPnl1.add(cancelBtn);
      JPanel btnPnl2 = new JPanel();
      btnPnl2.setLayout(new BoxLayout(btnPnl2, BoxLayout.X_AXIS));
      btnPnl2.add(modifyBtn);
      btnPnl2.add(deleteBtn);
      JPanel btnPnl3 = new JPanel();
      btnPnl3.setLayout(new BoxLayout(btnPnl3, BoxLayout.X_AXIS));
      btnPnl3.add(ordersBtn);
      GuiUtility.addComp(btnPnl1, p, gbl, gbc, 4, 0,
         1, GridBagConstraints.REMAINDER, 0, 0);
      GuiUtility.addComp(btnPnl2, p, gbl, gbc, 5, 0,
         1, GridBagConstraints.REMAINDER, 0, 0);
      GuiUtility.addComp(btnPnl3, p, gbl, gbc, 6, 0,
         1, GridBagConstraints.REMAINDER, 0, 0);
      return p;
   }

   /**
    * Creates the button that takes the user back to the parent
    * component, i.e. the frame from which s/he came before viewing
    * this frame.
    */
   private JPanel createReturnPanel()
   {  returnBtn = new JButton(ICDGUI.RETURN);
      returnBtn.addActionListener(new ActionListener()
      {  public void actionPerformed(ActionEvent ae)
         {  setVisible(false);
            parentComp.enableGUI();
            dispose();
         }
      });
      JPanel p = new JPanel();
      p.add(returnBtn);
      return p;
   }

   /**
    * Disables/enables parts of the GUI for when the user has no
    * customer selected.
    */
   private void setGUIForNoCustomerSelected()
   {  newBtn.setEnabled(true);
      insertBtn.setEnabled(false);
      cancelBtn.setEnabled(false);
      modifyBtn.setEnabled(false);
      deleteBtn.setEnabled(false);
      ordersBtn.setEnabled(false);
      custList.setEnabled(true);
      currentCustomer = null;
      displayCurrentCustomer();
      nameTF.setEnabled(false);
      houseStreetTF.setEnabled(false);
      townCountyTF.setEnabled(false);
      teleNumTF.setEnabled(false);
   }

   /**
    * Disables/enables parts of the GUI for when the user is viewing
    * a customer.
    */
   private void setGUIForCustomerViewing()
   {  newBtn.setEnabled(true);
      insertBtn.setEnabled(false);
      cancelBtn.setEnabled(false);
      modifyBtn.setEnabled(true);
      deleteBtn.setEnabled(true);
      ordersBtn.setEnabled(true);
      custList.setEnabled(true);
      displayCurrentCustomer();
      nameTF.setEnabled(true);
      houseStreetTF.setEnabled(true);
      townCountyTF.setEnabled(true);
      teleNumTF.setEnabled(true);
   }

   /**
    * Disables/enables parts of the GUI for when the user is entering
    * a new customer.
    */
   private void setGUIForCustomerEntry()
   {  newBtn.setEnabled(false);
      insertBtn.setEnabled(true);
      cancelBtn.setEnabled(true);
      modifyBtn.setEnabled(false);
      deleteBtn.setEnabled(false);
      ordersBtn.setEnabled(false);
      custList.setEnabled(false);
      currentCustomer = null;
      displayCurrentCustomer();
      nameTF.setEnabled(true);
      houseStreetTF.setEnabled(true);
      townCountyTF.setEnabled(true);
      teleNumTF.setEnabled(true);
   }

/* =======================================================================
       INSTANCE VARIABLES & CLASS VARIABLES
   =======================================================================
*/
   private ICDGUI parentComp;
   private CustomerCollection custCollection;
   private CDCollection cdCollection;

   private Customer currentCustomer;
   private Vector viewedCustomers;

   private JList custList;
   private JTextField searchIdNumTF;
   private JTextField searchNameTF;
   private JButton searchBtn;
   private JButton fullBtn;
   private ActionListener fullBtnLstnr;

   private JTextField idNumTF;
   private JTextField nameTF;
   private JTextField houseStreetTF;
   private JTextField townCountyTF;
   private JTextField teleNumTF;
   private JButton newBtn;
   private JButton insertBtn;
   private JButton cancelBtn;
   private JButton modifyBtn;
   private JButton deleteBtn;
   private JButton ordersBtn;

   private JButton returnBtn;

   private static final int ID_TF_COLS = 6;
   private static final int NAME_TF_COLS = 30;
   private static final int ADDRESS_TF_COLS = 30;
   private static final int TELE_TF_COLS = 10;

   private static final String SEARCH = "SEARCH";
   private static final String FULL = "See Full List";
   private static final String NEW = "NEW CUSTOMER";
   private static final String INSERT = "INSERT";
   private static final String CANCEL = "CANCEL";
   private static final String MODIFY = "Save Changes";
   private static final String DELETE = "DELETE";
   private static final String ORDERS = "ORDERS";
}
