package lab02;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;

public class Calculator extends JPanel {
	private static final long serialVersionUID = 1L;
	private static Font fontLarge;
	Display display;
	CPU cpu;
	Memory memory;
	JPanel buttons;
	String op;
	String mode;

	public Calculator() {
		op = "LOD"; mode="IMM";
		memory = new Memory(100);
		cpu = new CPU(memory);
		Font font = getFont();
		fontLarge = font.deriveFont((float) (2.5 * font.getSize2D()));
		setLayout(new BorderLayout());
		display = new Display();
		display.setFont(fontLarge);

		add(display, BorderLayout.PAGE_START);
		buttons = new JPanel(new GridLayout(6, 4));
		
		addButton("CE", (e) -> display.clearEntry());
		addButton("C", (e) -> execute("LOD", "IMM", 0));
		addButton("+/-", (e) -> display.setValue(-1 * display.getValue()));
		addButton("/", (e) -> executeNext("DIV","IMM"));

		addButton("7", (e) -> display.addNumber(7));
		addButton("8", (e) -> display.addNumber(8));
		addButton("9", (e) -> display.addNumber(9));
		addButton("x", (e) -> executeNext("MUL","IMM"));

		addButton("4", (e) -> display.addNumber(4));
		addButton("5", (e) -> display.addNumber(5));
		addButton("6", (e) -> display.addNumber(6));
		addButton("-", (e) -> executeNext("SUB","IMM"));

		addButton("1", (e) -> display.addNumber(1));
		addButton("2", (e) -> display.addNumber(2));
		addButton("3", (e) -> display.addNumber(3));
		addButton("+", (e) -> executeNext("ADD","IMM"));

		addButton("LOD", (e) -> {executeNext("LOD","DIR");});
		addButton("0", (e) -> display.addNumber(0));
		addButton("STO", (e) -> {executeNext("STO","DIR");}); 
		addButton("=", (e) -> executeNext("LOD","IMM"));

		add(buttons, BorderLayout.PAGE_END);
	}

	private void addButton(String name, ActionListener action) {
		JButton but = new JButton(name);
		but.setFont(fontLarge);
		but.addActionListener(action);
		buttons.add(but);
	}

	private void executeNext(String nextOp,String nextMode) {
		int arg = display.getValue();
		cpu.execute(op, mode, arg);
		display.setValue(cpu.getAccumulator());
		display.newNumber();
		op = nextOp;
		mode=nextMode;
		
	}

	private void execute(String op, String mode, int arg) {
		cpu.execute(op, mode, arg);
		display.setValue(cpu.getAccumulator());
	}

	private static void createAndShowGUI() {
		// Create and set up the window.
		JFrame frame = new JFrame("Java Calculator");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setContentPane(new Calculator());

		// Display the window.
		frame.pack();
		frame.setVisible(true);
	}

	public static void main(String[] args) {
		// Schedule a job for the event-dispatching thread:
		// creating and showing this application's GUI.
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() { createAndShowGUI(); }
		});

	}

	private class Display extends JLabel {
		private static final long serialVersionUID = 1L;
		int value;
		boolean newNumber;

		public Display() {
			super();
			setOpaque(true);
			setHorizontalAlignment(JLabel.RIGHT);
			setBackground(new Color(131, 213, 248));
			setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
			clearEntry();
		}

		public void clearEntry() {
			setValue(0);
			newNumber = true;
		}

		public void addNumber(int num) {
			if (newNumber) clearEntry();
			newNumber = false;
			setValue(value * 10 + num);
		}

		public void newNumber() { newNumber = true; }

		public void undo() { setValue(value / 10); }

		/**
		 * @return the value
		 */
		public int getValue() { return value; }

		/**
		 * @param value the value to set
		 */
		public void setValue(int value) {
			this.value = value;
			setText(String.format("%18d", value));
		}

	}
}