import java.awt.*;
import java.awt.event.*;
import javax.ejb.*;
import javax.swing.*;
import com.sun.ebank.ejb.customer.*;
import com.sun.ebank.util.CustomerDetails;
import javax.naming.*;
import com.sun.ebank.util.EJBGetter;
import com.sun.ebank.ejb.exception.*;
import java.rmi.RemoteException;

/*
  This class is an example of one class handling three functions. Refer 
  to the DataModel.java, EventHandle.java, and BankApp.java class files 
  for an example of how this code can be organized into three classes 
  according to their function: 1) building and manipulating the user
  interface, (BankApp) 2) handling events generated by the user interface
  (EventHandle), and 3) managing data between the user interface and the 
  database (DataModel). This class file includes C-style comments that 
  annotate how it was broken up and organized into the three separate classes. 
  Code not indicated here has being moved to either the EventHandle or
  DataModel class is in the BankApp class.
*/

public class BankAppNotOO extends JFrame implements ActionListener {
//Private instance variables
  private JButton view, add, panel, update, OK, cancel;
  private JPanel p1, p2;
  private static JFrame frame;
  //Labels
  private JLabel fnamelab, lnamelab, milab, streetlab, citylab, statelab;
  private JLabel ziplab, phonelab, emaillab, messlab, messlab2, messlab3, 
	  messlab4, messlab5, messlab6;
  //Read-Only variables
  private JTextArea fnamero, lnamero, miro, streetro, cityro, statero;
  private JTextArea zipro, phonero, ero;
  //Editable variables
  private JTextField fname, lname, mi, street, city, state;
  private JTextField zip, phone, e;
  //Data manipulation variables 
  private int which;
  private String mess, returned, first = null;
  /*These last variables are moved to the DataModel class because
    they are related to managing the data between the UI and
    the database.
  */
  private String last=null, mid=null, str=null, cty=null;
  private String st=null, zp=null, tel=null, mail=null, custID=null;
  //Bean lookup variables
  private CustomerControllerHome customerControllerHome = null;
  private CustomerController customer = null;

//Constructor creates initial UI (Panel 1)
  public BankAppNotOO() {
    getContentPane().setLayout(new GridLayout(1,2));
    p1 = new JPanel();
    p1.setLayout(new GridLayout(11,1));
    p2 = new JPanel();
    p1.setBackground(Color.white);
    p2.setBackground(Color.white);
    getContentPane().add(p1);
    getContentPane().add(p2);
    view = new JButton("View Cutomer Information");
    add = new JButton("Add New Customer");
    update = new JButton("Update Customer Information");
    messlab = new JLabel();
    messlab2 = new JLabel();
    messlab3 = new JLabel();
    messlab4 = new JLabel();
    messlab5 = new JLabel();
    messlab6 = new JLabel();
    view.addActionListener(this);
    add.addActionListener(this);
    update.addActionListener(this);
    p1.add(view);
    p1.add(add);
    p1.add(update);
    p1.add(new JLabel());
    p1.add(messlab);
    p1.add(messlab2);
    p1.add(messlab3);
    p1.add(messlab4);
    p1.add(messlab5);
    p1.add(messlab6);

//Look up and create CustomerController bean
  /*The lookup code is moved to the DataModel class because 
    it's related to reading from and writing to the database
  */
    try {
      InitialContext ctx = new InitialContext();
      customerControllerHome = EJBGetter.getCustomerControllerHome();
      customer = customerControllerHome.create();
    } catch (Exception NamingException) {
      NamingException.printStackTrace();
    }

//Add functionality to close window
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent event) {
        System.exit(0);
      }
    });
  }

  /*The actionPerformed method is moved to the
    EventHandle3 class because it is related to handling
    events generated by the user interface class.
  */ 
  public void actionPerformed(ActionEvent event) {
    Object source = event.getSource();
//View customer data
    if(source == view) {
      clearMessages();
      messlab5.setText(" View Customer Information");
      mess = new String("Enter Customer ID:");
      returned = JOptionPane.showInputDialog(frame, mess);
      if(returned != null) {
        which = 3;
        createCustInf(which);
      }
    }
//Add new customer
    if(source == add){
      clearMessages();
      messlab5.setText(" Add New Customer");
      which = 1;
      createCustInf(which);
    }
//Update customer data
    if(source == update){
      clearMessages();
      messlab5.setText(" Update Customer Information");
      mess = new String("Enter Customer ID:");
      returned = JOptionPane.showInputDialog(frame, mess); 
      if(returned != null) {
        which = 2;
        createCustInf(which);
      }
    }
//Process data
    if(source == OK) {
      if(which == 3) { //view data
        clearMessages();
        p2.removeAll();
        p2.setLayout(new FlowLayout());
        p2.validate();
        p2.repaint();
      } else if((which == 1) || (which == 2)) { //add or update data
       //Test data and write to database
        int complete = checkData();
      //If data okay, clear Panel 2
        if(complete == 0) {
	  clearMessages();
          p2.removeAll();
          p2.setLayout(new FlowLayout());
          p2.validate();
          p2.repaint();
        }
      //If errors, redisplay data to user 
      //and leave error messages on display
        if(complete == 1) {
          p2.removeAll();
	  p2.setLayout(new GridLayout(0, 2));
	  createPanel2Labels();
          createEditableFields(first, last, mid, str, cty, st, zp, tel, mail);
        }
      }
    } else { //OK with no ID supplied
      clearMessages();
    }
//Clear data on cancel button press
    if(source == cancel) {
      clearMessages();
      p2.removeAll();
      p2.setLayout(new FlowLayout());
      p2.validate();
      p2.repaint();
    }
  } //end actionPerformed

  public void clearMessages() {
      messlab.setText(null);
      messlab2.setText(null);
      messlab3.setText(null);
      messlab4.setText(null);
      messlab5.setText(null);
      messlab6.setText(null);
  }

  /*This method is moved to the DataModel class because it checks
    data before writing it to the database.
  */
  private int checkData() {
    int i, j, k;
    last = null, first = null, mid = null, str = null, cty = null;
    st = nul, zp = null, tel = null, mail = null;

  /*When you have a lot of if statements like this, you
    should consider whether you can use polymorphism
    instead. See the DataModel.getData method for an example
    of how to replace this code with one short polymorphic method t
  */
    if(lname.getText().length > 0) {
       String temp = lname.getText();
       last = temp.trim();
    } else {
      last = null;
    }

    if(fname.getText().length > 0) {
       String temp = lname.getText();
       first = temp.trim();
    } else {
      last = null;
    }

    if(mi.getText().length > 0) {
       String temp = lname.getText();
       mid = temp.trim();
    } else {
      last = null;
    }

    if(street.getText().length > 0) {
       String temp = lname.getText();
       str = temp.trim();
    } else {
      last = null;
    }

    if(city.getText().length > 0) {
       String temp = lname.getText();
       cty = temp.trim();
    } else {
      last = null;
    }

    if(state.getText().length > 0) {
       String temp = lname.getText();
       st = temp.trim();
    } else {
      last = null;
    }

    if(zip.getText().length > 0) {
       String temp = lname.getText();
       zp = temp.trim();
    } else {
      last = null;
    }

    if(phone.getText().length > 0) {
       String temp = lname.getText();
       tel = temp.trim();
    } else {
      last = null;
    }

    if(e.getText().length > 0) {
       String temp = lname.getText();
       mail = temp.trim();
    } else {
      last = null;
    }

    messlab2.setText(null);
    messlab3.setText(null);
    messlab4.setText(null);
    messlab5.setText(null);
    messlab6.setText(null);

    if((last != null) && (first != null) && (str != null)
                      && (cty != null) && (st != null)) {
      i = 0;
    } else {
      messlab6.setText(" Missing Required Information");
      i = 1;
    }
    if(mi.getText().length() > 1) {
      messlab2.setText(" MI has one-letter limit");
      j = 1;
    } else {
      j = 0;
    }
    if(state.getText().length() > 2) {
      messlab3.setText(" State has two-letter limit");
      k = 1;
    } else {
      k = 0;
    }
    if((i == 0) && (j == 0) && (k == 0)) {
      int success = writeData();
      return success; 
    } else { 
      return 1;
    } 
  }
  
  /*This method is moved to the DataModel class becuase it 
    writes data to the database.
  */
  private int writeData() {
    if(which == 2){ //Update customer information
      try {
        customer.setName(last, first, mid, returned);
        customer.setAddress(str, cty, st, zp, tel, mail, returned);
        return 0;
      } catch (RemoteException ex) {
        messlab.setText(" Remote Exception");
        return 1;
      } catch (CustomerNotFoundException ex) {
        messlab4.setText(" Customer not found");
        return 1;
      }
    } 

    if(which == 1) { //Add new customer information
      try {
        custID = customer.createCustomer(last, first, mid, str, cty, st, 
			zp, tel, mail);
        JOptionPane.showMessageDialog(frame, custID, "Customer ID", 
			JOptionPane.PLAIN_MESSAGE);
	return 0;
      } catch (RemoteException ex) {
        messlab.setText(" Remote Exception");
        return 1;
      }
    }
    return 0;
  }

  /*This method is moved to the DataModel class because it reads
    data frmo the database.
  */
  private void createCustInf(int which) {
    CustomerDetails details = null;
    p2.removeAll();
    p2.setLayout(new GridLayout(0, 2));
    createPanel2Labels();

  //View Data
    if((which == 3) && (returned.length() > 0)) { 
      try {
        details = customer.getDetails(returned); //CustID 
        createROFields(details.getFirstName(), details.getLastName(),
                details.getMiddleInitial(), details.getStreet(),
                details.getCity(), details.getState(), details.getZip(),
                details.getPhone(), details.getEmail());
      } catch (RemoteException ex) {
        messlab.setText(" Remote Exception");
      } catch (CustomerNotFoundException ex) {
        clearMessages();
        messlab4.setText(" Customer " + returned + " not found");
        p2.removeAll();
        p2.setLayout(new FlowLayout());
        p2.validate();
        p2.repaint();
      }
    }

  //Update Data
    if((which == 2) && (returned.length() > 0)) {
      try {
        details = customer.getDetails(returned);
        createEditableFields(details.getFirstName(), details.getLastName(),
                details.getMiddleInitial(), details.getStreet(),
                details.getCity(), details.getState(), details.getZip(),
                details.getPhone(), details.getEmail());
      } catch (RemoteException ex) {
        messlab.setText(" Remote Exception");
      } catch (CustomerNotFoundException ex) {
	clearMessages();
        messlab4.setText(" Customer " + returned + " not found");
        p2.removeAll();
        p2.setLayout(new FlowLayout());
        p2.validate();
        p2.repaint();
      }
    }

  //Add Data
    if(which == 1) {
      createEditableFields(null, null, null, null, null, 
		null, null, null, null);
    }
  }

  private void createPanel2Labels() {
    fnamelab = new JLabel("First name: (Required)");
    lnamelab = new JLabel("Last name: (Required)");
    milab = new JLabel("MI:");
    streetlab = new JLabel("Street: (Required)");
    citylab = new JLabel("City: (Required)");
    statelab = new JLabel("State (Required):");
    ziplab = new JLabel("Zip:");
    phonelab = new JLabel("Phone:");
    emaillab = new JLabel("Email:");
    OK = new JButton("OK");
    OK.addActionListener(this);
    cancel = new JButton("Cancel");
    cancel.addActionListener(this);
  }

  private void createROFields(String first, String last, String mid,
        String str, String cty, String st, String zp, String tel, String mail){
    fnamero = new JTextArea(first);
    lnamero = new JTextArea(last);
    miro = new JTextArea(mid);
    streetro = new JTextArea(str);
    cityro = new JTextArea(cty);
    statero = new JTextArea(st);
    zipro =   new JTextArea(zp);
    phonero = new JTextArea(tel);
    ero = new JTextArea(mail);
    p2.add(fnamelab);
    p2.add(fnamero);
    p2.add(lnamelab);
    p2.add(lnamero);
    p2.add(milab);
    p2.add(miro);
    p2.add(streetlab);
    p2.add(streetro);
    p2.add(citylab);
    p2.add(cityro);
    p2.add(statelab);
    p2.add(statero);
    p2.add(ziplab);
    p2.add(zipro);
    p2.add(phonelab);
    p2.add(phonero);
    p2.add(emaillab);
    p2.add(ero);
    p2.add(OK);
    p2.add(cancel);
    p2.validate();
    p2.repaint();

  }

  private void createEditableFields(String first, String last, String mid,
        String str, String cty, String st, String zp, String tel, String mail){
    fname = new JTextField(first);
    lname = new JTextField(last);
    mi = new JTextField(mid);
    street = new JTextField(str);
    city = new JTextField(cty);
    state = new JTextField(st);
    zip =   new JTextField(zp);
    phone = new JTextField(tel);
    e = new JTextField(mail);
    p2.add(fnamelab);
    p2.add(fname);
    p2.add(lnamelab);
    p2.add(lname);
    p2.add(milab);
    p2.add(mi);
    p2.add(streetlab);
    p2.add(street);
    p2.add(citylab);
    p2.add(city);
    p2.add(statelab);
    p2.add(state);
    p2.add(ziplab);
    p2.add(zip);
    p2.add(phonelab);
    p2.add(phone);
    p2.add(emaillab);
    p2.add(e);
    p2.add(OK);
    p2.add(cancel);
    p2.validate();
    p2.repaint();
  }

  public static void main(String args[]) {
    frame = new BankAppNotOO();
    frame.setTitle("Banking Administration Client");
    WindowListener l = new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
	System.exit(0);
      }
    };
    frame.addWindowListener(l);
    frame.pack();
    frame.setVisible(true);
    // Wait on anonymous object to prevent main from completing
    //Remove this code after bug is fixed
    Object o = new Object();
    synchronized(o) {
      try {
        o.wait();
      } catch(Exception e) {
        e.printStackTrace();
      }
    }
    //Remove to here
  }
}
