package com.mybank.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.io.IOException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;

import com.mybank.data.DataSource;
import com.mybank.db.DBService;
import com.mybank.domain.Bank;
import com.mybank.domain.Customer;
import com.mybank.domain.OverdraftException;

public class MyATM extends JFrame {

	JTextArea display = new JTextArea();
	JLabel input = new JLabel("", SwingConstants.CENTER);

	JPanel right = new JPanel(new GridLayout(2, 0));
	JPanel keypad = new JPanel(new GridLayout(4, 3));
	JPanel operation = new JPanel(new GridLayout(6, 0));

	JButton login = new JButton("Login");
	JButton checkBalance = new JButton("Check Balance");
	JButton deposit = new JButton("Deposit");
	JButton withdraw = new JButton("Withdraw");
	JButton quit = new JButton("Quit");

	int custId = 0;
	boolean found = false;
	Customer cust;

	public MyATM() {
		// configure frame
		setLayout(new BorderLayout());
		setResizable(false);

		// call function to add components to frame
		init();

		pack(); // prepare/package the frame
		setSize(800, 300);
		setVisible(true);
		// stop app when click close X
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setLocationRelativeTo(null); // centered
	}

	private void init() {
		// load data
//		DataSource dataSource = new DataSource("data/test.dat");
		try {
//			dataSource.loadData();
			DBService.loadData();
			
		} catch (Exception e) {
			// display error message
			display.setText("Error loading data: " + e.getMessage());
		}

		// setup gui
		setTitle("MyBank ATM");

		// display welcome message
		display.setText("== Welcome to MyBank ATM ==");
		display.append("\nPlease enter your Customer Id (1-4)");

		// configure input
		input.setSize(30, 10);

		// configure keypad
		keypad.setPreferredSize(new Dimension(200, 100));

		// prepare the keys
		String[] values = { "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "0", "C" };

		// add keys to keypad
		for (int i = 0; i < values.length; i++) {
			JButton btn = new JButton(values[i]);
			btn.addActionListener(e -> {
				if (btn.getText() == "C") {
					// clear the input
					input.setText("");
				} else {
					input.setText(input.getText() + btn.getText());
				}
			});
			keypad.add(btn);
		}

		// add keypad and operation to right panel
		operation.add(input);
		operation.add(login);
		operation.add(checkBalance);
		operation.add(deposit);
		operation.add(withdraw);
		operation.add(quit);

		right.add(keypad);
		right.add(operation);

		// add right panel to frame
		add(right, BorderLayout.EAST);

		// add display to frame
		JScrollPane left = new JScrollPane(display);
		left.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		add(left);

		// set action for operation buttons
		setOperationListener();

		// disable buttons
		loggedout();
	}

	private void updateCaret() {
		// set cursor (caret) always at the bottom of display
		display.setCaretPosition(display.getDocument().getLength());
	}

	private void loggedin() {
		login.setEnabled(false);
		checkBalance.setEnabled(true);
		deposit.setEnabled(true);
		withdraw.setEnabled(true);
		quit.setEnabled(true);
	}

	private void loggedout() {
		login.setEnabled(true);
		checkBalance.setEnabled(false);
		deposit.setEnabled(false);
		withdraw.setEnabled(false);
		quit.setEnabled(true);
	}

	private void setOperationListener() {
		// login button
		login.addActionListener(e -> {
			// get user id from input
			if (input.getText() != "") {
				custId = Integer.parseInt(input.getText());
				found = getCustomerDetails(custId);
				input.setText(""); // clear input
				loggedin();
			} else {
				display.append("\nEnter your Customer Id (1-4)");
				updateCaret();
			}
		});

		// check balance button
		checkBalance.addActionListener(e -> {
			// check if customer is found
			if (found) {
				// display customer's account balance
				display.append("\nYour current balance is " + cust.getAccount(0).getBalance());
				display.append("\nTo deposit or withdraw, enter amount.");
				updateCaret();
			}
		});

		// deposit button
		deposit.addActionListener(e -> {
			if (input.getText() != "") {
				// get the amount entered
				double amount = Double.parseDouble(input.getText());
				// update account balance
				cust.getAccount(0).deposit(amount);
				// display success message
				display.append("\nSuccessfully deposit " + amount + " into account.");
				display.append("\nYour new account balance is " + cust.getAccount(0).getBalance());
				display.append("\nTo deposit or withdraw, enter amount.");
			} else {
				display.append("\nPlease enter amount.");
			}
			updateCaret();
			// clear input
			input.setText("");
		});

		// withdraw button
		withdraw.addActionListener(e -> {
			if (input.getText() != "") {
				// get the amount entered
				double amount = Double.parseDouble(input.getText());
				try {
					// update account balance
					cust.getAccount(0).withdraw(amount);
					// display success message
					display.append("\nSuccessfully withdraw " + amount + " from account.");
					display.append("\nYour new account balance is " + cust.getAccount(0).getBalance());
					display.append("\nTo deposit or withdraw, enter amount.");

				} catch (OverdraftException ex) {
					display.append("\n" + ex.getMessage());
				}
			} else {
				display.append("\nPlease enter amount.");
			}
			updateCaret();
			// clear input
			input.setText("");
		});

		// quit button
		quit.addActionListener(e -> {
			// stop the app
			System.exit(0);
		});

	}

	private boolean getCustomerDetails(int id) {
		cust = Bank.getCustomer(id - 1);
		if (cust != null) {
			String msg = String.format("\nHello %s %s, please choose operation to continue", cust.getFirstName(),
					cust.getLastName());
			display.append(msg);
			updateCaret();
			return true;
		}
		return false;
	}

	public static void main(String[] args) {
		new MyATM(); // launch
	}
}
