import javax.swing.*; // for JFrame, JPanel, JTextField, JButton, JSlider, JTextArea, JLabel, etc.
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import java.awt.*; // for FlowLayout, GridLayout, BorderLayout, etc.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

@SuppressWarnings("serial")
public class MatrixCalculator extends JFrame {
	private static final int WIDTH = 800;
	private static final int HEIGHT = 600;
	private static final int FONT_SIZE = 14;

	JTextField[][] aFields;
	JTextField[][] bFields;
	JTextArea cArea;
	JLabel cLabel;

	JMenuBar menuBar;
	JMenu fileMenu;
	JMenuItem fileSaveMenuItem;
	JMenuItem fileSaveAsMenuItem;
	JMenuItem fileOpenDialogMenuItem;
	
	File saveFile = null;
	
	String matrixCalculatorTitle = "Matrix Calculator v.0.0_0";

	// ******************************************************
	public MatrixCalculator() {
		setTitle(matrixCalculatorTitle);
		setSize(WIDTH, HEIGHT);
		setLayout(new BorderLayout(15,25));
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		createContents();
		this.setLocationRelativeTo(null);
		setVisible(true);
	} // end MatrixCalculator constructor

	// ******************************************************
	private void createContents() {
		JPanel northPanel = new JPanel(new FlowLayout());
		JPanel southPanel = new JPanel(new FlowLayout());
		JPanel westPanel = new JPanel(new BorderLayout());
		JPanel eastPanel = new JPanel(new BorderLayout());
		JPanel centerPanel = new JPanel(new BorderLayout());
		JPanel westGridPanel = new JPanel(new GridLayout(3, 3));
		JPanel centerGridPanel = new JPanel(new GridLayout(3, 3));
		JPanel aHorizontalSliderPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		JPanel bHorizontalSliderPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));

		add(northPanel, BorderLayout.NORTH);
		add(southPanel, BorderLayout.SOUTH);
		cArea = new JTextArea();
		cArea.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		cArea.setText(new Matrix(3,3).toString());
		eastPanel.add(cArea, BorderLayout.CENTER);
		cLabel = new JLabel("C");
		cLabel.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		eastPanel.add(cLabel, BorderLayout.NORTH);
		add(eastPanel, BorderLayout.EAST);
		add(westPanel, BorderLayout.WEST);
		add(centerPanel, BorderLayout.CENTER);

		westPanel.add(westGridPanel, BorderLayout.CENTER);
		centerPanel.add(centerGridPanel, BorderLayout.CENTER);

		JSlider aHorizontal = new JSlider(JSlider.HORIZONTAL, 1, 10, 3);
		JSlider aVertical = new JSlider(JSlider.VERTICAL, 1, 10, 3);
		aVertical.setInverted(true);
		JSlider bHorizontal = new JSlider(JSlider.HORIZONTAL, 1, 10, 3);
		JSlider bVertical = new JSlider(JSlider.VERTICAL, 1, 10, 3);
		bVertical.setInverted(true);

		JLabel aLabel = new JLabel("A");
		aLabel.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		aHorizontalSliderPanel.add(aLabel);
		aHorizontalSliderPanel.add(aHorizontal);
		westPanel.add(aHorizontalSliderPanel, BorderLayout.NORTH);
		westPanel.add(aVertical, BorderLayout.WEST);

		JLabel bLabel = new JLabel("B");
		bLabel.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		bHorizontalSliderPanel.add(bLabel);
		bHorizontalSliderPanel.add(bHorizontal);
		centerPanel.add(bHorizontalSliderPanel, BorderLayout.NORTH);
		centerPanel.add(bVertical, BorderLayout.WEST);

		aHorizontal.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				westGridPanel.removeAll();
				int rows = aVertical.getValue();
				int cols = aHorizontal.getValue();
				westGridPanel.setLayout(new GridLayout(rows, cols));
				aFields = new JTextField[rows][cols];
				for (int i = 0; i < rows; i++) {
					for (int j = 0; j < cols; j++) {
						aFields[i][j] = new JTextField("0",5);
						westGridPanel.add(aFields[i][j]);
					}
				}
				validate();
				pack();
			}
		});

		aVertical.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				westGridPanel.removeAll();
				int rows = aVertical.getValue();
				int cols = aHorizontal.getValue();
				westGridPanel.setLayout(new GridLayout(rows, cols));
				aFields = new JTextField[rows][cols];
				for (int i = 0; i < rows; i++) {
					for (int j = 0; j < cols; j++) {
						aFields[i][j] = new JTextField("0",5);
						westGridPanel.add(aFields[i][j]);
					}
				}
				validate();
				pack();
			}
		});

		bHorizontal.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				centerGridPanel.removeAll();
				int rows = bVertical.getValue();
				int cols = bHorizontal.getValue();
				centerGridPanel.setLayout(new GridLayout(rows, cols));
				bFields = new JTextField[rows][cols];
				for (int i = 0; i < rows; i++) {
					for (int j = 0; j < cols; j++) {
						bFields[i][j] = new JTextField("0",5);
						centerGridPanel.add(bFields[i][j]);
					}
				}
				validate();
				pack();
			}
		});

		bVertical.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				centerGridPanel.removeAll();
				int rows = bVertical.getValue();
				int cols = bHorizontal.getValue();
				centerGridPanel.setLayout(new GridLayout(rows, cols));
				bFields = new JTextField[rows][cols];
				for (int i = 0; i < rows; i++) {
					for (int j = 0; j < cols; j++) {
						bFields[i][j] = new JTextField("0",5);
						centerGridPanel.add(bFields[i][j]);
					}
				}
				validate();
				pack();
			}
		});

		aFields = new JTextField[3][3];
		bFields = new JTextField[3][3];

		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				aFields[i][j] = new JTextField("0",5);
				aFields[i][j].setFont(new Font("", Font.PLAIN, FONT_SIZE));
				westGridPanel.add(aFields[i][j]);
			}
		}
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				bFields[i][j] = new JTextField("0",5);
				bFields[i][j].setFont(new Font("", Font.PLAIN, FONT_SIZE));
				centerGridPanel.add(bFields[i][j]);
			}
		}

		JButton addButton = new JButton("A + B");
		addButton.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		addButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int rows = aVertical.getValue();
				int cols = aHorizontal.getValue();

				if (rows != bVertical.getValue() || cols != bHorizontal.getValue()) {
					JOptionPane.showMessageDialog(null, "incorrect dimensions");
					return;
				}

				Matrix A = new Matrix(rows, cols);
				Matrix B = new Matrix(rows, cols);
				for (int i = 0; i < rows; i++) {
					for (int j = 0; j < cols; j++) {
						A.M[i][j] = new Fraction(aFields[i][j].getText());
						B.M[i][j] = new Fraction(bFields[i][j].getText());
					}
				}	
				Matrix C = A.add(B);
				cArea.setText(C.toString());
				cLabel.setText("C = A + B");
				pack();
			}
		});
		southPanel.add(addButton);

		JButton scalarMultiplyButton = new JButton("sA");
		scalarMultiplyButton.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		scalarMultiplyButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int aRows = aVertical.getValue();
				int aCols = aHorizontal.getValue();

				Matrix A = new Matrix(aRows, aCols);

				for (int i = 0; i < aRows; i++) {
					for (int j = 0; j < aCols; j++) {
						A.M[i][j] = new Fraction(aFields[i][j].getText());
					}
				}
				Fraction s = new Fraction(JOptionPane.showInputDialog("s: "));
				Matrix C = A.multiply(s);
				cArea.setText(C.toString());
				cLabel.setText("C = " + s + "A");
				pack();
			}
		});
		southPanel.add(scalarMultiplyButton);

		JButton subtractButton = new JButton("A - B");
		subtractButton.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		subtractButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int rows = aVertical.getValue();
				int cols = aHorizontal.getValue();

				if (rows != bVertical.getValue() || cols != bHorizontal.getValue()) {
					JOptionPane.showMessageDialog(null, "incorrect dimensions");
					return;
				}

				Matrix A = new Matrix(rows, cols);
				Matrix B = new Matrix(rows, cols);
				for (int i = 0; i < rows; i++) {
					for (int j = 0; j < cols; j++) {
						A.M[i][j] = new Fraction(aFields[i][j].getText());
						B.M[i][j] = new Fraction(bFields[i][j].getText());
					}
				}	
				Matrix C = A.add(B.multiply(new Fraction(-1,1)));
				cArea.setText(C.toString());
				cLabel.setText("C = A - B");
				pack();
			}
		});
		southPanel.add(subtractButton);

		JButton multiplyMButton = new JButton("AB");
		multiplyMButton.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		multiplyMButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {				
				int aRows = aVertical.getValue();
				int aCols = aHorizontal.getValue();

				int bRows = bVertical.getValue();
				int bCols = bHorizontal.getValue();

				if (bRows != aCols) {
					JOptionPane.showMessageDialog(null, "incorrect dimensions");
					return;
				}

				Matrix A = new Matrix(aRows, aCols);
				Matrix B = new Matrix(bRows, bCols);

				for (int i = 0; i < aRows; i++) {
					for (int j = 0; j < aCols; j++) {
						A.M[i][j] = new Fraction(aFields[i][j].getText());
					}
				}
				for (int i = 0; i < bRows; i++) {
					for (int j = 0; j < bCols; j++) {
						B.M[i][j] = new Fraction(bFields[i][j].getText());
					}
				}
				Matrix C = A.multiplyM(B);
				cArea.setText(C.toString());
				cLabel.setText("C = AB");
				pack();
			}
		});
		southPanel.add(multiplyMButton);

		JButton transposeButton = new JButton("A\u1D40");
		transposeButton.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		transposeButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				//
				//
				//
				// COMPLETE THIS METHOD (Use the other button click handlers as an example.)
				//
				//
				//
			}
		});
		southPanel.add(transposeButton);

		JButton determinantButton = new JButton("|A|");
		determinantButton.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		determinantButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				//
				//
				//
				// COMPLETE THIS METHOD (Use the other button click handlers as an example.)
				//
				//
				//
			}
		});
		southPanel.add(determinantButton);

		JButton inverseButton = new JButton("A\u207B\u00B9");
		inverseButton.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		inverseButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				//
				//
				//
				// COMPLETE THIS METHOD (Use the other button click handlers as an example.)
				//
				//
				//
			}
		});
		southPanel.add(inverseButton);

		JButton CtoA_Button = new JButton("C \u2192 A");
		CtoA_Button.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		CtoA_Button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				//
				//
				//
				// COMPLETE THIS METHOD (Use the other button click handlers as an example.)
				//
				//
				//
			}
		});
		southPanel.add(CtoA_Button);

		JButton CtoB_Button = new JButton("C \u2192 B");
		CtoB_Button.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		CtoB_Button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				//
				//
				//
				// COMPLETE THIS METHOD (Use the other button click handlers as an example.)
				//
				//
				//
			}
		});
		southPanel.add(CtoB_Button);

		JButton swapAandB_Button = new JButton("A \u2194 B");
		swapAandB_Button.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		swapAandB_Button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				//
				//
				//
				// COMPLETE THIS METHOD (Use the other button click handlers as an example.)
				//
				//
				//
			}
		});
		southPanel.add(swapAandB_Button);

		JButton exA_Button = new JButton("X \u2192 A");
		exA_Button.setFont(new Font("", Font.PLAIN, FONT_SIZE));
		exA_Button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				//
				//
				//
				// COMPLETE THIS METHOD (Use the other button click handlers as an example.)
				//
				//
				//
			}
		});
		southPanel.add(exA_Button);
		
		pack();
	} // end createContents

	// ******************************************************
	public static void main(String[] args) {
		new MatrixCalculator();
	} // end main
} // end class MatrixCalculator