UNB/ CS/ David Bremner/ teaching/ java/ ATMSimulation.java
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;

/**
   A simulation of an automatic teller machine
*/

public class ATMSimulation
{  public static void main(String[] args)
   {  ATM frame = new ATM();
      frame.setTitle("First National Bank of Java");      
      frame.show();
   }
}

class ATM extends JFrame
{  /**
      Constructs the user interface of the ATM application.
   */
   public ATM()
   {  final int FRAME_WIDTH = 500;
      final int FRAME_HEIGHT = 200;
      setSize(FRAME_WIDTH, FRAME_HEIGHT);
      
      addWindowListener(new WindowCloser());

      // initialize bank and customers

      theBank = new Bank();
      try
      {  theBank.readCustomers("customers.txt");
      }
      catch(IOException e)
      {  JOptionPane.showMessageDialog
            (null, "Error opening accounts file.");
      }
   
      // construct components

      pad = new KeyPad();

      display = new JTextArea(4, 20);
      
      aButton = new JButton("  A  ");
      aButton.addActionListener(new AButtonListener());

      bButton = new JButton("  B  ");
      bButton.addActionListener(new BButtonListener());

      cButton = new JButton("  C  ");
      cButton.addActionListener(new CButtonListener());
      
      // add components to content pane

      JPanel buttonPanel = new JPanel();
      buttonPanel.setLayout(new GridLayout(3, 1));
      buttonPanel.add(aButton);
      buttonPanel.add(bButton);
      buttonPanel.add(cButton);
      
      Container contentPane = getContentPane();
      contentPane.setLayout(new FlowLayout());
      contentPane.add(pad);
      contentPane.add(display);
      contentPane.add(buttonPanel);

      setState(START_STATE);      
   }
   
   /** 
      Sets the current customer number to the keypad value
      and sets state to PIN.
   */
   public void setCustomerNumber() 
   {  customerNumber = (int)pad.getValue();
      setState(PIN_STATE);
   }

   /** 
      Gets PIN from keypad, finds customer in bank.
      If found sets state to ACCOUNT, else to START.
   */
   public void selectCustomer()
   {  int pin = (int)pad.getValue();
      currentCustomer 
         = theBank.findCustomer(customerNumber, pin);
      if (currentCustomer == null) 
         setState(START_STATE);
      else 
         setState(ACCOUNT_STATE);
   }
   
   /** 
      Sets current account to checking or savings. Sets 
      state to TRANSACT
      @param account one of Customer.CHECKING_ACCOUNT
      or Customer.SAVINGS_ACCOUNT
   */
   public void selectAccount(int account)
   {  currentAccount = currentCustomer.getAccount(account);
      setState(TRANSACT_STATE);
   }

   /** 
      Withdraws amount typed in keypad from current account. 
      Sets state to ACCOUNT. 
   */
   public void withdraw()
   {  currentAccount.withdraw(pad.getValue());
      setState(ACCOUNT_STATE);
   }

   /** 
      Deposits amount typed in keypad to current account. 
      Sets state to ACCOUNT. 
   */
   public void deposit()
   {  currentAccount.deposit(pad.getValue());
      setState(ACCOUNT_STATE);
   }

   /** 
      Sets state and updates display message.
      @param state the next state
   */
   public void setState(int newState)
   {  state = newState;
      pad.clear();
      if (state == START_STATE)
         display.setText("Enter customer number\nA = OK");
      else if (state == PIN_STATE)
         display.setText("Enter PIN\nA = OK");
      else if (state == ACCOUNT_STATE)
         display.setText("Select Account\n" 
           + "A = Checking\nB = Savings\nC = Exit");
      else if (state == TRANSACT_STATE)
         display.setText("Balance = " 
            + currentAccount.getBalance() 
            + "\nEnter amount and select transaction\n"
            + "A = Withdraw\nB = Deposit\nC = Cancel");
   }
   
   private int state;
   private int customerNumber;
   private Customer currentCustomer;
   private BankAccount currentAccount;
   private Bank theBank;
   
   private JButton aButton;
   private JButton bButton;
   private JButton cButton;
   
   private KeyPad pad;
   private JTextArea display;
   
   private static final int START_STATE = 1;
   private static final int PIN_STATE = 2;
   private static final int ACCOUNT_STATE = 3;
   private static final int TRANSACT_STATE = 4;

   private class AButtonListener implements ActionListener
   {  public void actionPerformed(ActionEvent event)
      {  if (state == START_STATE)
            setCustomerNumber();
         else if (state == PIN_STATE)
            selectCustomer();
         else if (state == ACCOUNT_STATE)
            selectAccount(Customer.CHECKING_ACCOUNT);
         else if (state == TRANSACT_STATE)
            withdraw();
      }
   }
   
   private class BButtonListener implements ActionListener
   {  public void actionPerformed(ActionEvent event)
      {  if (state == ACCOUNT_STATE)
            selectAccount(Customer.SAVINGS_ACCOUNT);
         else if (state == TRANSACT_STATE)
            deposit();
      }
   }

   private class CButtonListener implements ActionListener
   {  public void actionPerformed(ActionEvent event)
      {  if (state == ACCOUNT_STATE)
            setState(START_STATE);
         else if (state == TRANSACT_STATE)
            setState(ACCOUNT_STATE);
      }
   }

   private class WindowCloser extends WindowAdapter
   {  public void windowClosing(WindowEvent event)
      {  System.exit(0);
      }
   }
}