import javax.swing.JOptionPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Font;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.File;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Scanner;

public class ATM {
    
    // these must be declared here to be seen in the Action classes
    JFrame welcomeFrame;
    JFrame inputFrame;
    JFrame mainFrame;
    JFrame interestFrame;
    JFrame zeroRateFrame;
    Graphics2D thePen;
    JTextField numberField;
    JTextField pinField;
    JTextField interestField;
    JTextField principleField;
    JTextField yearsField;
    JTextField compoundField;
    JTextField costField;
    JTextField timeField;
    JTextField bondPrincipleField;
    JLabel verifyLabel;
    JLabel outLabel;
    JButton depositButton;
    JButton withdrawButton;
    JButton makeDepositButton;
    JButton makeWithdrawalButton;
    BankAccount theAccount;
    NumberFormat currency;
    double theAmount;
    int width;
    int height;
    ArrayList<BankAccount> accounts;
    
    public ATM() throws IOException {
        
        welcomeFrame = new JFrame("Welcome to the ATM");
        welcomeFrame.setSize(300,200);
        mainFrame = new JFrame("ATM");
        mainFrame.setSize(400,500);
        interestFrame = new JFrame("Interest Calculator");
        interestFrame.setSize(300,350);
        zeroRateFrame = new JFrame("Zero Rate Interest Calculator");
        zeroRateFrame.setSize(300,350);
        int xLocation = 200;
        int yLocation = 200;
        welcomeFrame.setLocation(xLocation,yLocation);
        inputFrame = new JFrame("Enter Amount");
        inputFrame.setSize(200,100);
        inputFrame.setLocation(xLocation,yLocation);
        mainFrame.setLocation(xLocation,yLocation);
        interestFrame.setLocation(xLocation,yLocation);
        zeroRateFrame.setLocation(xLocation,yLocation);
        mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        welcomeFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        inputFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        interestFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        zeroRateFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        
        JPanel welcomePanel = new JPanel();
        welcomePanel.setLayout(new FlowLayout(FlowLayout.CENTER,200,20));
        welcomePanel.setPreferredSize(new Dimension(400,200));
        JButton closeButton = new JButton("Close ATM");
        closeButton.addActionListener(new CloseAction());
        
        JPanel interestCalculationPanel = new JPanel();
        interestCalculationPanel.setLayout(new FlowLayout(FlowLayout.CENTER,200,20));
        interestCalculationPanel.setPreferredSize(new Dimension(400,300));
        JPanel interestPanel = new JPanel();
        JLabel interestLabel = new JLabel("Enter interest");
        interestField = new JTextField("0.05",5);
        interestPanel.add(interestLabel);
        interestPanel.add(interestField);
        JPanel principlePanel = new JPanel();
        JLabel principleLabel = new JLabel("Enter initial priciple");
        principleField = new JTextField("100.00",10);
        JPanel yearsPanel = new JPanel();
        JLabel yearsLabel=  new JLabel("Enter number of years");
        yearsField = new JTextField("2",5);
        yearsPanel.add(yearsLabel);
        yearsPanel.add(yearsField);
        JPanel compoundPanel = new JPanel();
        JLabel compoundLabel=  new JLabel("Enter compound times per year");
        compoundField = new JTextField("1",5);
        compoundPanel.add(compoundLabel);
        compoundPanel.add(compoundField);
        principlePanel.add(principleLabel);
        principlePanel.add(principleField);
        interestCalculationPanel.add(interestPanel);
        interestCalculationPanel.add(principlePanel);
        interestCalculationPanel.add(yearsPanel);
        interestCalculationPanel.add(compoundPanel);
        JButton calculateButton = new JButton("Calculate");
        calculateButton.addActionListener(new CalculateButtonAction());
        JPanel calculateButtonPanel = new JPanel();
        calculateButtonPanel.add(calculateButton);
        interestCalculationPanel.add(calculateButtonPanel);
        
        JPanel zeroRateCalculationPanel = new JPanel();
        zeroRateCalculationPanel.setLayout(new FlowLayout(FlowLayout.CENTER,200,20));
        zeroRateCalculationPanel.setPreferredSize(new Dimension(400,300));
        JPanel costPanel = new JPanel();
        JLabel costLabel = new JLabel("Enter price of bond");
        costField = new JTextField("97.50",7);
        costPanel.add(costLabel);
        costPanel.add(costField);
        JPanel timePanel = new JPanel();
        JLabel timeLabel = new JLabel("Enter time to maturity in years");
        timeField = new JTextField("0.25",5);
        timePanel.add(timeLabel);
        timePanel.add(timeField);
        JPanel bondPrinciplePanel = new JPanel();
        JLabel bondPrincipleLabel=  new JLabel("Enter Bond Principle");
        bondPrincipleField = new JTextField("100",10);
        bondPrinciplePanel.add(bondPrincipleLabel);
        bondPrinciplePanel.add(bondPrincipleField);
        zeroRateCalculationPanel.add(costPanel);
        zeroRateCalculationPanel.add(timePanel);
        zeroRateCalculationPanel.add(bondPrinciplePanel);
        JButton calculate1Button = new JButton("Calculate");
        calculate1Button.addActionListener(new Calculate1ButtonAction());
        JPanel calculate1ButtonPanel = new JPanel();
        calculate1ButtonPanel.add(calculate1Button);
        zeroRateCalculationPanel.add(calculate1ButtonPanel);
        
        JLabel pinLabel = new JLabel("Enter pin and Press Enter");
        pinField = new JTextField(10);
        pinField.addActionListener(new PinFieldAction());
        welcomePanel.add(pinLabel);
        welcomePanel.add(pinField);
        welcomePanel.add(closeButton);
        
        // the main frame panel
        JPanel thePanel = new JPanel();
        width = 500;
        height = 400;
        thePanel.setPreferredSize(new Dimension(width,height));
        thePanel.setBackground(Color.LIGHT_GRAY);
        thePanel.setLayout(new FlowLayout(FlowLayout.CENTER,200,20));
        
        JPanel inputPanel = new JPanel();
        
        JLabel numberLabel = new JLabel("Type Amount and Press Enter");
        numberField = new JTextField(10);
        numberField.addActionListener(new NumberFieldAction());
        inputPanel.add(numberLabel);
        inputPanel.add(numberField);
        
        JPanel verifyPanel = new JPanel();
        verifyLabel = new JLabel("No Amount Entered");
        verifyPanel.add(verifyLabel);
        
        JPanel choosePanel = new JPanel();
        JLabel chooseLabel = new JLabel("Choose Transaction");
        choosePanel.add(chooseLabel);
        
        JPanel buttonPanel = new JPanel();
        JPanel makeButtonPanel = new JPanel();
        
        JButton balanceButton = new JButton("Balance");
        balanceButton.addActionListener(new BalanceButtonAction());
        buttonPanel.add(balanceButton);
        
        depositButton = new JButton("Deposit");
        depositButton.addActionListener(new DepositButtonAction());
        buttonPanel.add(depositButton);
        
        withdrawButton = new JButton("Withdraw");
        withdrawButton.addActionListener(new WithdrawButtonAction());
        buttonPanel.add(withdrawButton);
        
        makeDepositButton = new JButton("Make Deposit");
        makeDepositButton.addActionListener(new MakeDepositButtonAction());
        makeButtonPanel.add(makeDepositButton);
        
        makeWithdrawalButton = new JButton("Make Withdrawal");
        makeWithdrawalButton.addActionListener(new MakeWithdrawalButtonAction());
        makeButtonPanel.add(makeWithdrawalButton);
        
        JButton interestButton = new JButton("Interest Calculator");
        interestButton.addActionListener(new InterestButtonAction());
        
        JButton zeroRateButton = new JButton("Calculate Zero Rate");
        zeroRateButton.addActionListener(new ZeroRateButtonAction());
        
        JButton finishButton = new JButton("Finish");
        finishButton.addActionListener(new FinishButtonAction());
        
        JButton finishButton1 = new JButton("Finish");
        finishButton1.addActionListener(new Finish1ButtonAction());
        
        JButton finishButton2 = new JButton("Finish");
        finishButton2.addActionListener(new Finish2ButtonAction());
        
        JPanel outPanel = new JPanel();
        outPanel.setPreferredSize(new Dimension(width,height/4));
        outPanel.setBackground(Color.LIGHT_GRAY);
        outLabel = new JLabel("");
        outPanel.add(outLabel);
        
        thePanel.add(choosePanel);
        thePanel.add(verifyPanel);
        thePanel.add(buttonPanel);
        thePanel.add(makeButtonPanel);
        thePanel.add(interestButton);
        thePanel.add(zeroRateButton);
        JPanel finishPanel = new JPanel();
        finishPanel.add(finishButton);
        thePanel.add(finishPanel);
        thePanel.add(outPanel);
        
        welcomeFrame.add(welcomePanel);
        welcomeFrame.setVisible(true);
        
        mainFrame.add(thePanel);
        
        inputFrame.add(inputPanel);
        
        interestCalculationPanel.add(finishButton1);
        interestFrame.add(interestCalculationPanel);
        
        zeroRateCalculationPanel.add(finishButton2);
        zeroRateFrame.add(zeroRateCalculationPanel);
        
        outLabel.setForeground(Color.RED);
        outLabel.setFont(new Font("monospaced",Font.BOLD,20));
        
        currency = NumberFormat.getCurrencyInstance();
        
        accounts = new ArrayList<BankAccount>();
        Scanner in = new Scanner(new File("accounts.data"));
        while( in.hasNext() ) {
            accounts.add(new BankAccount(in.next(),in.nextDouble()));
        } // end while
        
    } // end constructor
    
    class PinFieldAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            String pinInput = pinField.getText();
            Scanner check = new Scanner(pinInput);
            if( !check.hasNextInt()) {
                JOptionPane.showMessageDialog(null,"Enter Only Digits");
                return;
            } // end if
            int pin = accounts.indexOf(new BankAccount(pinInput));
            if( pin == -1 ) {
                JOptionPane.showMessageDialog(null,"Invalid Pin");
                return;
            } // end if
            theAccount = (BankAccount)accounts.get(pin);
            welcomeFrame.setVisible(false);
            mainFrame.setVisible(true);
            pinField.setText("");
        } // end actionPerformed
    } // end PinFieldAction
    
    class NumberFieldAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            // these are the statements that are executed when enter is pressed in the numberField
            Scanner input = new Scanner(numberField.getText());
            if( !isInputOK(input,numberField) ) return;
            theAmount = input.nextDouble();
            welcomeFrame.setVisible(false);
            inputFrame.setVisible(false);
            mainFrame.setVisible(true);
            verifyLabel.setText("Amount Entered was " + currency.format(theAmount));
        } // end actionPerformed
    } // end NumberButtonAction
    
    class BalanceButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            drawBalance(theAccount);
        } // end actionPerformed
    } // end BalanceButtonAction
    
    class DepositButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            inputFrame.setVisible(true);
            numberField.setText("");
            numberField.requestFocus();
            makeDepositButton.setEnabled(true);
            //withdrawButton.setEnabled(false);
            makeWithdrawalButton.setEnabled(false);
        } // end actionPerformed
    } // end DepositButtonAction
    
    class WithdrawButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            inputFrame.setVisible(true);
            numberField.setText("");
            numberField.requestFocus();
            //depositButton.setEnabled(false);
            makeDepositButton.setEnabled(false);
            makeWithdrawalButton.setEnabled(true);
        } // end actionPerformed
    } // end WithdrawButtonAction
    
    class MakeDepositButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            if( !isAmountOK(theAmount) ) return;
            theAccount.deposit(theAmount);
            theAmount = 0.0;
            verifyLabel.setText("No Amount Entered");
            drawBalance(theAccount);
            withdrawButton.setEnabled(true);
            makeWithdrawalButton.setEnabled(true);
        } // end actionPerformed
    } // end MakeDepositButtonAction
    
    class MakeWithdrawalButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            if( !isAmountOK(theAmount) ) return;
            theAccount.withdraw(theAmount);
            theAmount = 0.0;
            verifyLabel.setText("No Amount Entered");
            drawBalance(theAccount);
            depositButton.setEnabled(true);
            makeDepositButton.setEnabled(true);
        } // end actionPerformed
    } // end MakeWithDrawalButtonAction
    
    class InterestButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            outLabel.setText("");
            mainFrame.setVisible(false);
            interestFrame.setVisible(true);
        } // end actionPerformed
    } // end InterestButtonAction
    
    class ZeroRateButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            outLabel.setText("");
            mainFrame.setVisible(false);
            zeroRateFrame.setVisible(true);
        } // end actionPerformed
    } // end InterestButtonAction
    
    class CalculateButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            Scanner input = new Scanner(interestField.getText());
            if( !isInputOK(input,interestField) ) return;
            double interest = input.nextDouble();
            input = new Scanner(principleField.getText());
            if( !isInputOK(input,principleField) ) return;
            double principle = input.nextDouble();
            input = new Scanner(yearsField.getText());
            if( !isInputOK(input,yearsField) ) return;
            int years = (int)input.nextDouble();
            input = new Scanner(compoundField.getText());
            if( !isInputOK(input,compoundField) ) return;
            int compound = (int)input.nextDouble();
            
            // add code here to calculate the money earned
            // and display the amount in a JOptionPane
            
        } // end actionPerformed
    } // end CalculateButtonAction    
    
    class Calculate1ButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            DecimalFormat interest = new DecimalFormat("#.#####");
            Scanner input = new Scanner(costField.getText());
            if( !isInputOK(input,costField) ) return;
            double cost = input.nextDouble();
            input = new Scanner(timeField.getText());
            if( !isInputOK(input,timeField) ) return;
            double time = input.nextDouble();
            input = new Scanner(bondPrincipleField.getText());
            if( !isInputOK(input,bondPrincipleField) ) return;
            double bondPrinciple = input.nextDouble();
            
            // add code here to calculate the zero rate 
            // with continuous compounding in a JOptionPane
            
        } // end actionPerformed
    } // end CalculateButtonAction
    
    class FinishButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            outLabel.setText("");
            mainFrame.setVisible(false);
            inputFrame.setVisible(false);
            interestFrame.setVisible(false);
            welcomeFrame.setVisible(true);
            depositButton.setEnabled(true);
            withdrawButton.setEnabled(true);
        } // end actionPerformed
    } // end FinishButtonAction
    
    class Finish1ButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            outLabel.setText("");
            mainFrame.setVisible(true);
            interestFrame.setVisible(false);
            depositButton.setEnabled(true);
            withdrawButton.setEnabled(true);
        } // end actionPerformed
    } // end FinishButtonAction
    
    class Finish2ButtonAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            outLabel.setText("");
            mainFrame.setVisible(true);
            zeroRateFrame.setVisible(false);
            depositButton.setEnabled(true);
            withdrawButton.setEnabled(true);
        } // end actionPerformed
    } // end FinishButtonAction
    
    class CloseAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            System.exit(0);
        }
    }// end CloseAction
    
    boolean isInputOK(Scanner input,JTextField field) {
        if( !input.hasNextDouble() && !input.hasNextInt() ) {
            JOptionPane.showMessageDialog(null,"Invalid input. Try again.");
            field.requestFocus();
            return false;
        } // end if
        return true;
    } // end is InputOK
    
    boolean isAmountOK(double amount)	 {
        if( amount <= 0.0 ) {
            JOptionPane.showMessageDialog(null, "Enter a positive amount");
            return false;
        } // end if
        return true;
    } // isAmountOK
    
    void drawBalance(BankAccount account) {
        outLabel.setText("The balance is " + currency.format(theAccount.getBalance()) + ".");
    } // end drawBalance
    
    public static void main(String[] args) throws IOException {
        new ATM();
    } // end main
    
} // end ATM4
