import javax.swing.*;		// For Timer
import java.awt.event.*;	// For ActionListener

/**
 * <BR>You can read the source of this class <A HREF="./Debugger_std.java.html"> here</A>.
 */
public abstract class Debugger_std implements Debugger {

// Constructors
	public Debugger_std() {
		pic = new DebuggablePIC_std();
		DisplayFlash();
		DisplayAll();
		Running = false;
		Stop = false;
		SymbolicInfo = true;
	}

	public Debugger_std(DigitalComponentUI dui) {
		pic = new DebuggablePIC_std(dui);
		DisplayFlash();
		DisplayAll();
		Running = false;
		Stop = false;
		SymbolicInfo = true;
	}

	public PIC getPIC() {
		return pic;
	}
// Execution methods
	public void Animate() {
		if(!Running) {
			Running = true;

			timer = new Timer(300, new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
						int oldPC = pic.getPC();
						pic.Trace();
						RefreshFlash(oldPC);
						RefreshFlash(pic.getPC());
						DisplayAll();


						if(pic.isBreakpoint(pic.getPC()) || Stop) {
							RefreshFlash(pic.getPC());

							DisplayInstruction();

							Link.ui().Stopped();
							Running = false;
							Stop = false;
							timer.stop();
						}
				}
			});
			timer.start();
/*			Thread t = new Thread() {
				public void run() {
					Running = true;

					// To remove the ">"
					int oldPC = pic.getPC();
					pic.Trace();
					RefreshFlash(oldPC);
					DisplayAll();


					while(!pic.isBreakpoint(pic.getPC()) && !Stop) {
						pic.Trace();
						DisplayAll();

						double i;
						for(i = 0 ; i < 1000 ; i+=.1);
					}
					RefreshFlash(pic.getPC());
					DisplayInstruction();

					Link.ui().Stopped();
					Running = false;
					Stop = false;
				}
			};

			t.start();*/
		}
	}

	public void Trace() {
		if(!Running) {
			int oldPC = pic.getPC();

			pic.Trace();
			RefreshFlash(oldPC);
			RefreshFlash(pic.getPC());
			DisplayAll();
		}
	}

	public void StepOver() {
		if(!Running) {
			if(Disassembler.Disassemble(pic.getFlashMemory().Read(pic.getPC())).substring(0, 4).compareTo("call") == 0) {
				int bpaddr = pic.getPC() + 1;
				Running = true;

				// To remove the ">"
				int oldPC = pic.getPC();
				pic.Trace();
				RefreshFlash(oldPC);

				while(!(bpaddr == pic.getPC())) {
					pic.Trace();
				}
				RefreshFlash(pic.getPC());
				DisplayInstruction();
				DisplayAll();
				Running = false;
			}
			else
				Trace();
		}
	}

	public void Run() {
		if(!Running) {
			Thread t = new Thread() {
				public void run() {
					Running = true;

					// To remove the ">"
					int oldPC = pic.getPC();
					pic.Trace();
					RefreshFlash(oldPC);

					while(!pic.isBreakpoint(pic.getPC()) && !Stop) {
						pic.Trace();
					}
	System.out.println("Stopped");
					RefreshFlash(pic.getPC());
	System.out.println(">");
					DisplayInstruction();
	System.out.println("go to >");
					DisplayAll();

					Link.ui().Stopped();
					Running = false;
					Stop = false;
				}
			};

			t.start();
		}
	}

	public void Stop() {
		Stop = true;
	}

	public boolean Running() {
		return Running;
	}

	public int getLabelAddress(int index) {
		return pic.getFlashMemory().getProgram().getLabelSymb()[index].address();
	}

// Program load methods
	public void LoadProgram(CompiledProgram prog) {
		pic.ReprogramFlash(prog);
		pic.Reset();
		DisplayFlash();
		RefreshFlash(pic.getPC());
		DisplayAll();
	}

	public void LoadProgram(String fn) {
		LoadProgram(new CompiledProgram(fn));
	}

	public void SaveProgram(String filename) {
		pic.getFlashMemory().getProgram().Save(filename);
	}
// Source code manipulation methods
	public void UpdateSource(String s) {
		src = new SourceCode(SourceCode.StringArrayFromString(s));
	}

	public void LoadSource(String filename) {
		src = new SourceCode(filename);
	}

	public void SaveSource(String filename) {
		src.Save(filename);
	}

	public void AssembleAndLoadSource() {
		pic.ReprogramFlash(Assembler.Assemble(src, SymbolicInfo));
		pic.Reset();
		DisplayFlash();
		RefreshFlash(pic.getPC());
		DisplayAll();
	}

// Display methods
/*	public void DisplayFileRegisters() {
	}

	public void DisplayFlash() {
	}

	public void DisplayState() {
	}

	public void DisplayInstruction() {
	}

	public void DisplayStack() {
	}

	public void RefreshFlash(int n) {
	}*/

	public void DisplayAll() {
		DisplayState();
		DisplayStack();
		DisplayInstruction();
		DisplayFileRegisters();
	}

	public void DisplayBreakpoints() {
	}

// Breakpoints
	public int GetBreakpoint(int n) {
		return pic.getBreakpoint(n);
	}

	public void SetBreakpoint(int n) {
		pic.setBreakpoint(n);
		DisplayBreakpoints();
		RefreshFlash(n);
	}

	public boolean IsBreakpoint(int n) {
		return pic.isBreakpoint(n);
	}

	public void RemoveBreakpoint(int n) {
		pic.removeBreakpoint(n);
		DisplayBreakpoints();
		RefreshFlash(n);
	}

	public int getPC() {
		return pic.getPC();
	}

	public void setPC(int n) {
		int oldPC = pic.getPC();
		pic.setPC(n);
		RefreshFlash(oldPC);
		RefreshFlash(n);
		DisplayState();
	}

// Protected variables
	protected DebuggablePIC pic;
	protected SourceCode src;
	protected boolean Running, Stop, SymbolicInfo;
	protected Timer timer;
}