package dev.sillyangel.calc;

import dev.sillyangel.calc.themes.MacDarkRed;
import dev.sillyangel.calc.CalculatorModes;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.UIManager;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JTextField;
import javax.swing.JComboBox;
import java.awt.GridLayout;
import java.awt.Image;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.ActionEvent;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.List;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JLabel;

public class Calculator extends JFrame implements KeyListener {

	private static final long serialVersionUID = 1L;
	private JPanel contentPane;
	private JTextField display;
	private String operand1;
	private String operator;
	private String operand2;
	private JButton btnDiv;
	private JButton btnMul;
	private JButton btnMin;
	private JButton btnPlus;
	protected boolean resultVisible;
	protected double result;
	private String[] Modes = new String[] {"Standard", "Scientific", "Data calculation"};
	private JComboBox<String> modeselect;

	public static void main(String[] args) {
//		IntelliJTheme.setup(Calculator.class.getResourceAsStream("/DarkPurple.theme.json"));
//		FlatMacDarkLaf.setup();
		MacDarkRed.setup();
		try {
//			UIManager.setLookAndFeel("com.formdev.flatlaf.themes.FlatMacDarkLaf");
			
		} catch (Throwable e) {
			e.printStackTrace();
		}
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Calculator frame = new Calculator();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	public Calculator() {
		setBackground(new Color(32, 32, 32));
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//		setIconImage(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon.png")));
		List<Image> icons = new ArrayList<>();
		icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon16.png")));
		icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon32.png")));
		icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon48.png")));
		icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon256.png")));
		icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon512.png")));
		icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon1024.png")));
		setIconImages(icons);

		setTitle("angel's awesome calculator");
		setBounds(100, 100, 368, 556);
		setFocusable(true);
		addKeyListener(this);

		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);

		display = new JTextField();
		display.setEditable(false);
		display.setFont(new Font("Segoe UI", Font.PLAIN, 22));
		display.setColumns(10);
		JPanel buttonPanel = new JPanel();

		addComponentListener(new ComponentAdapter() {
			@Override
			public void componentResized(ComponentEvent e) {
				Dimension size = e.getComponent().getSize();
				System.out.println("Window resized to " + size.width + "x" + size.height);
			}
		});

		JPanel panel = new JPanel();
		GroupLayout gl_contentPane = new GroupLayout(contentPane);
		gl_contentPane.setHorizontalGroup(
			gl_contentPane.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_contentPane.createSequentialGroup()
					.addContainerGap()
					.addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING)
						.addComponent(display, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 359, Short.MAX_VALUE)
						.addComponent(buttonPanel, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 359, Short.MAX_VALUE))
					.addContainerGap())
				.addComponent(panel, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 379, Short.MAX_VALUE)
		);
		gl_contentPane.setVerticalGroup(
			gl_contentPane.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_contentPane.createSequentialGroup()
					.addComponent(panel, GroupLayout.PREFERRED_SIZE, 36, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(display, GroupLayout.PREFERRED_SIZE, 78, GroupLayout.PREFERRED_SIZE)
					.addGap(27)
					.addComponent(buttonPanel, GroupLayout.PREFERRED_SIZE, 359, GroupLayout.PREFERRED_SIZE)
					.addContainerGap(199, Short.MAX_VALUE))
		);

		buttonPanel.setLayout(new GridLayout(0, 4, 0, 0));

		modeselect = new JComboBox<>(Modes);
		modeselect.addActionListener(new ActionListener() {
			@SuppressWarnings("unchecked")
			public void actionPerformed(ActionEvent e) {
				JComboBox<String> cb = (JComboBox<String>)e.getSource();
				String Mode = (String)cb.getSelectedItem();
				UpdateMode(Mode);
			}
		});
		modeselect.setEditable(false);
		modeselect.setFocusable(false);

		JButton btnNewButton_1 = new JButton("New button");
		btnNewButton_1.setFocusable(false);
		JLabel lblNewLabel = new JLabel("New label");
		lblNewLabel.setFocusable(false);

		btnNewButton_1.setVisible(false);
		lblNewLabel.setVisible(false);
		
		panel.add(modeselect);
		panel.add(lblNewLabel);
		panel.add(btnNewButton_1);

		JButton btnPercent = new JButton("%");
		JButton btnClearEntry = new JButton("CE");
		JButton btnReciprocal = new JButton("1/x");
		JButton btnSquare = new JButton("x²");
		JButton btnSquareRoot = new JButton("√x");

		// Use FlatLaf Tree.icon.collapsed as backspace-like icon (or just use text)
		JButton btnBackspace = new JButton("⌫");
		JButton btnClear = new JButton("C");
		JButton btnPlusMin = new JButton("+/-");
		JButton btnDot = new JButton(".");
		JButton btnEq = new JButton("=");

		JButton btn0 = new JButton("0");
		JButton btn1 = new JButton("1");
		JButton btn2 = new JButton("2");
		JButton btn3 = new JButton("3");
		JButton btn4 = new JButton("4");
		JButton btn5 = new JButton("5");
		JButton btn6 = new JButton("6"); // why was 6 afraid of 7... because 7 8 9 :sob:
		JButton btn7 = new JButton("7"); // 67!
		JButton btn8 = new JButton("8");
		JButton btn9 = new JButton("9");

		btnDiv = new JButton("/");
		btnMul = new JButton("*");
		btnMin = new JButton("-");
		btnPlus = new JButton("+");

		btnDot.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String n = display.getText(); // get the text on the display
				if (n.contains(".")) return; // if it already contains a "." skip rest of this
				processDigit(e.getActionCommand());

			}
		});

		btnEq.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				math();
			}
		});

		btnBackspace.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				backspace();
			}
		});

		btnClearEntry.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				clearEntry();
			}
		});

		btnClear.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				clearAll();
			}
		});

		btnPlus.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setOperator(e.getActionCommand());
			}
		});

		btnDiv.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setOperator(e.getActionCommand());
			}
		});

		btnMul.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setOperator(e.getActionCommand());
			}
		});

		btnMin.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setOperator(e.getActionCommand());
			}
		});

		btn0.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				processDigit(e.getActionCommand());
			}
		});

		btn1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				processDigit(e.getActionCommand());
			}
		});

		btn2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				processDigit(e.getActionCommand());
			}
		});

		btn3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				processDigit(e.getActionCommand());
			}
		});

		btn4.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				processDigit(e.getActionCommand());
			}
		});

		btn5.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				processDigit(e.getActionCommand());
			}
		});
		btn6.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				processDigit(e.getActionCommand());
			}
		});

		btn7.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				processDigit(e.getActionCommand());
			}
		});

		btn8.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				processDigit(e.getActionCommand());
			}
		});

		btn9.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				processDigit(e.getActionCommand());
			}
		});

		btnPlusMin.addActionListener(new ActionListener() {
		    public void actionPerformed(ActionEvent e) {
		        String tmp = display.getText();
		        if (tmp == null || tmp.isEmpty()) return;
		        char first = tmp.charAt(0);
		        if (first == '-') {
		            tmp = tmp.substring(1, tmp.length());
		            display.setText(tmp);
		        } else {
		            display.setText("-" + tmp);
		        }
		    }
		});

		btnPercent.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setOperator("%");
			}
		});

		btnReciprocal.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				reciprocal();
			}
		});

		btnSquare.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				square();
			}
		});

		btnSquareRoot.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				squareRoot();
			}
		});



		btnBackspace.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnClear.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnClearEntry.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnPlusMin.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnEq.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnDot.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btn0.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btn1.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btn2.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btn3.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btn4.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btn5.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btn6.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btn7.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btn8.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btn9.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnMul.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnMin.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnDiv.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnPlus.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnPercent.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnReciprocal.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnSquare.setFont(new Font("Segoe UI", Font.PLAIN, 29));
		btnSquareRoot.setFont(new Font("Segoe UI", Font.PLAIN, 29));

		// Make all buttons non-focusable so keyboard input always goes to the frame because if we don't it breaks
		btnBackspace.setFocusable(false);
		btnClear.setFocusable(false);
		btnClearEntry.setFocusable(false);
		btnPlusMin.setFocusable(false);
		btnEq.setFocusable(false);
		btnDot.setFocusable(false);
		btn0.setFocusable(false);
		btn1.setFocusable(false);
		btn2.setFocusable(false);
		btn3.setFocusable(false);
		btn4.setFocusable(false);
		btn5.setFocusable(false);
		btn6.setFocusable(false);
		btn7.setFocusable(false);
		btn8.setFocusable(false);
		btn9.setFocusable(false);
		btnMul.setFocusable(false);
		btnMin.setFocusable(false);
		btnDiv.setFocusable(false);
		btnPlus.setFocusable(false);
		btnPercent.setFocusable(false);
		btnReciprocal.setFocusable(false);
		btnSquare.setFocusable(false);
		btnSquareRoot.setFocusable(false);

		buttonPanel.add(btnPercent);
		buttonPanel.add(btnClearEntry);
		buttonPanel.add(btnClear);
		buttonPanel.add(btnBackspace);
		buttonPanel.add(btnReciprocal);
		buttonPanel.add(btnSquare);
		buttonPanel.add(btnSquareRoot);
		buttonPanel.add(btnDiv);
		buttonPanel.add(btn7);
		buttonPanel.add(btn8);
		buttonPanel.add(btn9);
		buttonPanel.add(btnMul);
		buttonPanel.add(btn4);
		buttonPanel.add(btn5);
		buttonPanel.add(btn6);
		buttonPanel.add(btnMin);
		buttonPanel.add(btn1);
		buttonPanel.add(btn2);
		buttonPanel.add(btn3);
		buttonPanel.add(btnPlus);
		buttonPanel.add(btnPlusMin);
		buttonPanel.add(btn0);
		buttonPanel.add(btnDot);
		buttonPanel.add(btnEq);

		contentPane.setLayout(gl_contentPane);

	}

	void UpdateMode(String Mode) {
		if (Mode == "Standard") {
			System.out.println("User has Selected Standard");
		} else if (Mode == "Scientific") {
//			System.out.println("User has Selected Scientific Calculator");
			CalculatorModes.Scientific();
		} else if (Mode == "Data calculation") {
//			System.out.println("User has Selected Date calculation mode");
			CalculatorModes.DateCalculation();
		} else {
			System.out.println(Mode);
		}
	}

	void backspace() {
		String tmp = display.getText();
		if (tmp.length()>1) // if there is more than 1 character
		    display.setText( tmp.substring(0, tmp.length()-1) );
		else // otherwise just make display empty
		    display.setText("");
	}

	void clearEntry() {
		// Clear only the current display (entry)
		display.setText("");
	}

	void clearAll() {
		// Clear everything including operands and operator
		display.setText("");
		operand1 = "";
		operand2 = "";
		operator = "";
		resultVisible = false;
	}

	void reciprocal() {
		String tmp = display.getText();
		if (tmp == null || tmp.isEmpty()) return;
		double value = Double.parseDouble(tmp);
		if (value != 0) {
			result = 1.0 / value;
			display.setText("" + result);
			resultVisible = true;
		}
	}

	void square() {
		String tmp = display.getText();
		if (tmp == null || tmp.isEmpty()) return;
		double value = Double.parseDouble(tmp);
		result = value * value;
		display.setText("" + result);
		resultVisible = true;
	}

	void squareRoot() {
		String tmp = display.getText();
		if (tmp == null || tmp.isEmpty()) return;
		double value = Double.parseDouble(tmp);
		if (value >= 0) {
			result = Math.sqrt(value);
			display.setText("" + result);
			resultVisible = true;
		}
	}

	void processDigit(String actionCommand) {
		if (resultVisible == true) {
			display.setText("");
			resultVisible = false;
		}
		display.setText(display.getText() + actionCommand);

	}
	void setOperator(String daop) {
		operand1 = display.getText();
		operator = daop;
		display.setText("");
	}

    void math() {
		operand2 = display.getText();
		double op1 = Double.parseDouble(operand1);
		double op2 = Double.parseDouble(operand2);

		if (operator == "+") {
			result = op1+op2;
		} else if (operator == "-") {
			result = op1-op2;
		} else if (operator == "*") {
			result = op1*op2;
		} else if (operator == "/") {
			result = op1/op2;
		} else if (operator == "%") {
			result = op1 % op2;
		} else {
			result = op2;
			System.out.println("Op: " + op1);
			System.out.println("Op2: " + op2);
		}

		operator = "";
		operand1 = "";
		operand2 = "";

		resultVisible = true;
		display.setText(""+result);
	}

    // Implement the keyPressed method
    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
//       System.out.println("Key Pressed: " + KeyEvent.getKeyText(keyCode));
       if (KeyEvent.getKeyText(keyCode) == "Enter") {
    	   math();
       } else if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
    	   backspace();
       }
    }

    // Implement the keyReleased method
    @Override
    public void keyReleased(KeyEvent e) {
//        int keyCode = e.getKeyCode();
//       System.out.println("Key Released: " + KeyEvent.getKeyText(keyCode));
    }

    // Implement the keyTyped method
    @Override
    public void keyTyped(KeyEvent e) {
       char c = e.getKeyChar();
//       System.out.println("Key Typed: " + keyChar);
        System.out.println(c + " KT");
        if (c >= '0' && c <= '9') {
        	processDigit(String.valueOf(c));
        }
        if (c == '+') {
        	setOperator("+");
        } else if (c == '*') {
        	setOperator("*");
        } else if (c == '/') {
        	setOperator("/");
        } else if (c == '-') {
        	setOperator("-");
        }
        if (c == '=') {
        	math();
        }

    }
}
