package playingcoffee.ui;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.DefaultListModel;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import playingcoffee.core.CPU;
import playingcoffee.core.MMU;
import javax.swing.JCheckBox;

public class CPUDebugger {

	private JFrame frmCpuDebugger;
	private JList<String> registerList;
	
	private MMU mmu;
	private CPU cpu;
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					CPUDebugger window = new CPUDebugger();
					window.frmCpuDebugger.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	public CPUDebugger() {
		initialize();
		
		mmu = new MMU();
		cpu = new CPU(mmu);
		
		mmu.loadBootRom();
		
		updateValues();
	}
	
	private void updateValues() {
		DefaultListModel<String> model = new DefaultListModel<String>();
		model.addElement("AF: 0x" + Integer.toHexString(cpu.getRegisters().readAF()));
		model.addElement("BC: 0x" + Integer.toHexString(cpu.getRegisters().readBC()));
		model.addElement("DE: 0x" + Integer.toHexString(cpu.getRegisters().readDE()));
		model.addElement("HL: 0x" + Integer.toHexString(cpu.getRegisters().readHL()));
		model.addElement("PC: 0x" + Integer.toHexString(cpu.getRegisters().pc));
		model.addElement("SP: 0x" + Integer.toHexString(cpu.getRegisters().sp));
		
		registerList.setModel(model);
	}

	private void initialize() {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
				| UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
		
		frmCpuDebugger = new JFrame();
		frmCpuDebugger.setTitle("CPU Debugger");
		frmCpuDebugger.setBounds(100, 100, 350, 350);
		frmCpuDebugger.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		JButton btnStep = new JButton("Step");
		btnStep.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				cpu.cycle();
				updateValues();
			}
		});
		
		JButton btnReset = new JButton("Reset");
		
		JLabel lblRegisters = new JLabel("Registers:");
		
		registerList = new JList<String>();
		
		JLabel lblFlags = new JLabel("Flags:");
		
		JCheckBox chckbxZero = new JCheckBox("Zero");
		GroupLayout groupLayout = new GroupLayout(frmCpuDebugger.getContentPane());
		groupLayout.setHorizontalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
						.addComponent(lblRegisters)
						.addComponent(btnStep)
						.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 148, GroupLayout.PREFERRED_SIZE))
					.addGap(11)
					.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
						.addGroup(groupLayout.createSequentialGroup()
							.addPreferredGap(ComponentPlacement.RELATED, 94, Short.MAX_VALUE)
							.addComponent(btnReset))
						.addGroup(Alignment.TRAILING, groupLayout.createSequentialGroup()
							.addComponent(chckbxZero)
							.addGap(108))
						.addComponent(lblFlags))
					.addContainerGap())
		);
		groupLayout.setVerticalGroup(
			groupLayout.createParallelGroup(Alignment.TRAILING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(lblRegisters)
						.addComponent(lblFlags))
					.addPreferredGap(ComponentPlacement.RELATED)
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(registerList, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE)
						.addComponent(chckbxZero))
					.addGap(51)
					.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
						.addComponent(btnReset)
						.addComponent(btnStep))
					.addContainerGap())
		);
		frmCpuDebugger.getContentPane().setLayout(groupLayout);
	}
}
