// using Java Swing
package sim;

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import sim.engine.EngineModule;
import sim.lib.memory.*;
import sim.lib.others.*;

public class ControlCenter implements TableModelListener, ActionListener {

	private JFrame frame;
	private ArrayList<Module> modList;
	private ArrayList<Rom> romList;
	private ArrayList<Ram> ramList;
	private JTable modTable;
	private JTable romTable;
	private JTable ramTable;
	private JTextField modText;
	private JTextField romText;
	private JTextField ramText;

	public ControlCenter() {
		initialiseList();
		frame = new JFrame("Control Center");
		frame.setSize(600, 600);
		frame.setLocation(MainWindow.getMiddleOfScreen(frame));
		frame.getContentPane().setLayout(new GridLayout(1, 1));

		JTabbedPane tab = new JTabbedPane();

		//Module Control Center

		tab.addTab("Module", createModPane());
		tab.addTab("ROM", createRomPane());
		tab.addTab("RAM", createRamPane());
		frame.getContentPane().add(tab, BorderLayout.CENTER);

		frame.setVisible(false);
	}

	private void initialiseList() {
		modList = new ArrayList();
		romList = new ArrayList();
		ramList = new ArrayList();

		int wires = CentralPanel.ACTIVE_GRID.getNumberOfWires();
		int junctions = CentralPanel.ACTIVE_GRID.getNumberOfJunctions();
		int splitters = CentralPanel.ACTIVE_GRID.getNumberOfSplitters();
		int components = CentralPanel.ACTIVE_GRID.getNumberOfComponents();
		int total = junctions + wires + splitters + components;

		for (int loop = junctions + wires + splitters; loop < total; loop++) {
			EngineModule em = (EngineModule) CentralPanel.ACTIVE_GRID.getComponent(loop);
			String type = em.getClass().toString();
			if (type.toString().equals("class sim.lib.others.Module")) {
				modList.add((Module) em);
			} else if (type.equals("class sim.lib.memory.Rom")) {
				romList.add((Rom) em);
			} else if (type.equals("class sim.lib.memory.Ram")) {
				ramList.add((Ram) em);
			}
		}
	}

	//Module Panel
	private JPanel createModPane() {
		JPanel panel = new JPanel(new BorderLayout());

		//table
		DefaultTableModel model = new DefaultTableModel() {
			@Override
			public Class<?> getColumnClass(int col) {
				if (col == 2) {
					return Boolean.class;
				} else {
					return String.class;
				}
			}
		};
		model.setColumnIdentifiers(new Object[]{"Module", "Module File Path", ""});
		for (int i = 0; i < modList.size(); i++) {

			model.addRow(new Object[]{modList.get(i).getLabel(), modList.get(i).getPath(), false});
		}
		model.addTableModelListener(this);

		modTable = new JTable(model);
		modTable.setRowHeight(30);
		JScrollPane scroll = new JScrollPane(modTable);
		panel.add(scroll, BorderLayout.CENTER);

		//apply to all
		JPanel p = new JPanel(new BorderLayout());

		// 2 buttons
		JPanel p2 = new JPanel(new FlowLayout());

		JButton modCheckAll = new JButton("Select ALL");
		modCheckAll.setActionCommand("Module All");
		modCheckAll.addActionListener(this);
		p2.add(modCheckAll);

		JButton modCheckNone = new JButton("Select None");
		modCheckNone.setActionCommand("Module None");
		modCheckNone.addActionListener(this);
		p2.add(modCheckNone);

		p.add(p2, BorderLayout.NORTH);

		// Text, Textfield, Apply button
		JLabel text = new JLabel("Change selected Module File Path to: ");
		p.add(text, BorderLayout.WEST);

		modText = new JTextField();
		p.add(modText, BorderLayout.CENTER);

		JButton modApplyButton = new JButton("Apply");
		modApplyButton.setActionCommand("Module Apply");
		modApplyButton.addActionListener(this);
		p.add(modApplyButton, BorderLayout.EAST);

		panel.add(p, BorderLayout.SOUTH);

		return panel;
	}

	//Rom Panel
	private JPanel createRomPane() {
		JPanel panel = new JPanel(new BorderLayout());

		//table
		DefaultTableModel model = new DefaultTableModel() {
			@Override
			public Class<?> getColumnClass(int col) {
				if (col == 2) {
					return Boolean.class;
				} else {
					return String.class;
				}
			}
		};
		model.setColumnIdentifiers(new Object[]{"ROM", "ROM File Path", ""});
		for (int i = 0; i < romList.size(); i++) {
			model.addRow(new Object[]{romList.get(i).getComponentName(), romList.get(i).getFile(), false});
		}
		model.addTableModelListener(this);
		romTable = new JTable(model);
		romTable.setRowHeight(30);
		JScrollPane scroll = new JScrollPane(romTable);
		panel.add(scroll, BorderLayout.CENTER);

		//apply to all
		JPanel p = new JPanel(new BorderLayout());

		//2 buttons
		JPanel p2 = new JPanel(new FlowLayout());

		JButton romCheckAll = new JButton("Select ALL");
		romCheckAll.setActionCommand("Rom All");
		romCheckAll.addActionListener(this);
		p2.add(romCheckAll);

		JButton romCheckNone = new JButton("Select None");
		romCheckNone.setActionCommand("Rom None");
		romCheckNone.addActionListener(this);
		p2.add(romCheckNone);

		p.add(p2, BorderLayout.NORTH);

		// Text, Textfield, Apply button
		JLabel text = new JLabel("Change selected ROM File Path to: ");
		p.add(text, BorderLayout.WEST);

		romText = new JTextField();
		p.add(romText, BorderLayout.CENTER);

		JButton romApplyButton = new JButton("Apply");
		romApplyButton.setActionCommand("Rom Apply");
		romApplyButton.addActionListener(this);
		p.add(romApplyButton, BorderLayout.EAST);

		panel.add(p, BorderLayout.SOUTH);

		return panel;
	}

	//Ram Panel
	private JPanel createRamPane() {
		JPanel panel = new JPanel(new BorderLayout());

		//table
		DefaultTableModel model = new DefaultTableModel() {
			@Override
			public Class<?> getColumnClass(int col) {
				if (col == 2) {
					return Boolean.class;
				} else {
					return String.class;
				}
			}
		};
		model.setColumnIdentifiers(new Object[]{"RAM", "RAM File Path", ""});
		for (int i = 0; i < ramList.size(); i++) {
			model.addRow(new Object[]{ramList.get(i).getComponentName(), ramList.get(i).getFile(), false});
		}
		model.addTableModelListener(this);

		ramTable = new JTable(model);
		ramTable.setRowHeight(30);
		JScrollPane scroll = new JScrollPane(ramTable);
		panel.add(scroll, BorderLayout.CENTER);

		//apply to all
		JPanel p = new JPanel(new BorderLayout());

		//2 buttons
		JPanel p2 = new JPanel(new FlowLayout());

		JButton ramCheckAll = new JButton("Select ALL");
		ramCheckAll.setActionCommand("Ram All");
		ramCheckAll.addActionListener(this);
		p2.add(ramCheckAll);

		JButton ramCheckNone = new JButton("Select None");
		ramCheckNone.setActionCommand("Ram None");
		ramCheckNone.addActionListener(this);
		p2.add(ramCheckNone);

		p.add(p2, BorderLayout.NORTH);

		// Text, Textfield, Apply button
		JLabel text = new JLabel("Change selected RAM File Path to: ");
		p.add(text, BorderLayout.WEST);

		ramText = new JTextField();
		p.add(ramText, BorderLayout.CENTER);

		JButton ramApplyButton = new JButton("Apply");
		ramApplyButton.setActionCommand("Ram Apply");
		ramApplyButton.addActionListener(this);
		p.add(ramApplyButton, BorderLayout.EAST);

		panel.add(p, BorderLayout.SOUTH);

		return panel;
	}

	public void setVisible(boolean visible) {
		frame.setVisible(visible);
	}

	@Override
	public void tableChanged(TableModelEvent e) {
		int row = e.getFirstRow();
		int column = e.getColumn();
		TableModel model = (TableModel) e.getSource();
		String tableName = model.getColumnName(0);
		Object data = model.getValueAt(row, column);

		//Module
		if (tableName.equals("Module")) {
			Module module = modList.get(row);
			// change name
			if (column == 0) {
				System.out.println(data.toString());
				module.setLabel(data.toString());
			} // change file
			else if (column == 1) {
				module.setPath(data.toString());
			}
			CentralPanel.ACTIVE_GRID.eraseComponent(module, false);
			CentralPanel.ACTIVE_GRID.paintComponent(module);
		}
		//ROM
		if (tableName.equals("ROM")) {
			Rom rom = romList.get(row);
			// change name
			if (column == 0) {
				System.out.println(data.toString());
				rom.setComponentName(data.toString());
			} // change file
			else if (column == 1) {
				rom.setFile(data.toString());
			}
			rom.initializeMemory();
			CentralPanel.ACTIVE_GRID.eraseComponent(rom, false);
			CentralPanel.ACTIVE_GRID.paintComponent(rom);
		}
		//RAM
		if (tableName.equals("RAM")) {
			Ram ram = ramList.get(row);
			// change name
			if (column == 0) {
				System.out.println(data.toString());
				ram.setComponentName(data.toString());
			} // change file
			else if (column == 1) {
				ram.setFile(data.toString());
			}
			ram.initializeMemory();
			CentralPanel.ACTIVE_GRID.eraseComponent(ram, false);
			CentralPanel.ACTIVE_GRID.paintComponent(ram);
		}
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		//module
		if (e.getActionCommand().equals("Module All")) {
			for (int i = 0; i < modList.size(); i++) {
				modTable.setValueAt(true, i, 2);
			}
		}
		if (e.getActionCommand().equals("Module None")) {
			for (int i = 0; i < modList.size(); i++) {
				modTable.setValueAt(false, i, 2);
			}
		}
		if (e.getActionCommand().equals("Module Apply")) {
			String newFile = modText.getText();
			for (int i = 0; i < modList.size(); i++) {
				if (((Boolean) modTable.getValueAt(i, 2)).booleanValue()) {
					modTable.setValueAt(newFile, i, 1);
					modTable.setValueAt(false, i, 2);
				}
			}
		}
		//rom
		if (e.getActionCommand().equals("Rom All")) {
			for (int i = 0; i < romList.size(); i++) {
				romTable.setValueAt(true, i, 2);
			}
		}
		if (e.getActionCommand().equals("Rom None")) {
			for (int i = 0; i < romList.size(); i++) {
				romTable.setValueAt(false, i, 2);
			}
		}
		if (e.getActionCommand().equals("Rom Apply")) {
			String newFile = romText.getText();
			for (int i = 0; i < romList.size(); i++) {
				if (((Boolean) romTable.getValueAt(i, 2)).booleanValue()) {
					romTable.setValueAt(newFile, i, 1);
					romTable.setValueAt(false, i, 2);
				}
			}
		}
		//ram
		if (e.getActionCommand().equals("Ram All")) {
			for (int i = 0; i < ramList.size(); i++) {
				ramTable.setValueAt(true, i, 2);
			}
		}
		if (e.getActionCommand().equals("Ram None")) {
			for (int i = 0; i < ramList.size(); i++) {
				ramTable.setValueAt(false, i, 2);
			}
		}
		if (e.getActionCommand().equals("Ram Apply")) {
			String newFile = ramText.getText();
			for (int i = 0; i < ramList.size(); i++) {
				if (((Boolean) ramTable.getValueAt(i, 2)).booleanValue()) {
					ramTable.setValueAt(newFile, i, 1);
					ramTable.setValueAt(false, i, 2);
				}
			}
		}
	}
}
