/**
 *  TEDController.java 
 *
 *  Copyright 2005 Ben Pfistner and Jason Emmons
 *
 *  This class controlls all interaction between the interface and the current Turing Machine.
 *  
 *
 */

import java.io.*;
// java.lang.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;


public class TEDController
{
	TEDInterface gui;
	TEDTM currentTM;
	TEDTM backupTM;
	int headAt;
	
	/**
	 *  Constructor
	 *
	 */
	
	
	public TEDController()
	{
		gui = new TEDInterface(this);
		currentTM = null;
	}
	
	/**
	 *  validate()
	 *
	 *  This method takes the User-entered input and creates a parser to deal with it.
	 *
	 */
	
	public boolean validate()
	{
		StringBuffer alphabetInput = new StringBuffer(gui.alphabetTF.getText());
		StringBuffer tapeInput = new StringBuffer(gui.tapeTF.getText());
		StringBuffer rulesInput = new StringBuffer(gui.rulesTA.getText());
		
		TEDParser parser = new TEDParser(); 
		return parser.validate(alphabetInput, tapeInput, rulesInput, this);		
	}
	
	
	/**
	 *  loadMachine()
	 *
	 *  This method loads the Turing Machine once it passes through the parser.
	 *  This method also creates a backup TM in case the user wants to reset the currentTM
	 *
	 *  @param theTM: the Turing Machine which was created by the parser.
	 *
	 */
	public void loadMachine(TEDTM theTM)
	{
		currentTM = theTM;
		backupTM = theTM.copy();
	}
	
	
	/**
	 *  doSave()
	 *
	 *  This method saves the current TM to a file
	 *
	 */
	public void doSave()
	{
		try
		{
			FileDialog outDialog = new FileDialog(gui, "Output File", FileDialog.SAVE);
			
			outDialog.show();
			if (outDialog.getFile() == null)		// Did user cancel?
				return;
			PrintWriter output = new PrintWriter(new FileWriter(
				new File(outDialog.getDirectory(), outDialog.getFile())));
	
			output.println(gui.alphabetTF.getText());
			output.println(gui.tapeTF.getText());
		
			
			if(currentTM != null)
			{
				output.println("{");
				Iterator keyIter = currentTM.stateMap.keySet().iterator();
		
				while(keyIter.hasNext())
				{	
					TEDState currentState = (TEDState)currentTM.stateMap.get(keyIter.next());
					
					ArrayList tupleList = currentState.getArray();
					Iterator tupleIter = tupleList.iterator();
					
					while(tupleIter.hasNext())
					{
						output.println(((TED5tuple)tupleIter.next()).toString() + ",");
					}
				}
							
				output.println("}");
			}
			else
			{
				output.println(gui.rulesTA.getText());	
			}
			
			output.close();
			
			JOptionPane.showMessageDialog(null, "File Successfully Saved");
		}
		catch(Exception e)
		{
			
			JOptionPane.showMessageDialog(null, "The File did NOT save successfully.");
			return;	
		}
	}
	
	
	/**
	 *  doLoad()
	 *
	 *  This method loads the current TM from a file
	 *
	 */
	public void doLoad()
	{
		try
		{
			FileDialog inDialog = new FileDialog(gui, "Input File", FileDialog.LOAD);
			
			inDialog.show();
			if (inDialog.getFile() == null) // Did user cancel?
				return;		
			BufferedReader input = new BufferedReader(new FileReader(
				new File(inDialog.getDirectory(), inDialog.getFile())));
				
			gui.alphabetTF.setText(input.readLine());
			gui.tapeTF.setText(input.readLine());
			
			StringBuffer rulesSB = new StringBuffer();
			
			rulesSB.append(input.readLine());
			
			try
			{
				StringBuffer inputLine = new StringBuffer(input.readLine());
			
				while(inputLine.indexOf("}") == -1)
				{		
					while(inputLine.indexOf(" ") != -1)
					{
						inputLine.deleteCharAt(inputLine.indexOf(" "));	
					}
					
					rulesSB.append(inputLine);
					
					inputLine = new StringBuffer(input.readLine());
				}//end while
				
				rulesSB.deleteCharAt(rulesSB.length()-1);
				rulesSB.append('}');
			}
			catch(Exception z)
			{
					
			}
			gui.rulesTA.setText(rulesSB.toString());
			
			input.close();
		}
		catch(Exception e)
		{
			gui.alphabetTF.setText("");
			gui.tapeTF.setText("");
			gui.rulesTA.setText("");
			JOptionPane.showMessageDialog(null, "The File failed to load.");	
		}	
	}
	
	/**
	 *  stepSpeed()
	 *
	 *  This method runs the TM at Step Speed
	 *
	 */
	public void stepSpeed()
	{
		currentTM.stepSpeed();	
	}
	
	
	/**
	 *  runSpeed()
	 *
	 *  This method runs the TM at Run Speed
	 *
	 */
	public void runSpeed()
	{
		Thread t = new Thread(currentTM);
		t.start();
	}
	
	
	/**
	 *  ludicrousSpeed()
	 *
	 *  This method runs the TM at Ludicrous Speed
	 *
	 */
	//contrary to jason, this is not a midget who is moving wicked fast with a pencil
	//.......
	// this is almost as dangerous as running with scissors but not quite....
	public void ludicrousSpeed()
	{
		try
		{
			FileDialog outDialog = new FileDialog(gui, "Output File", FileDialog.SAVE);
			
			outDialog.show();
			if (outDialog.getFile() == null)		// Did user cancel?
				return;
			PrintWriter printOut = new PrintWriter(new FileWriter(
				new File(outDialog.getDirectory(), outDialog.getFile())));
				
			currentTM.ludicrousSpeed(printOut);
		}
		catch(Exception e)
		{
			return;	
		}	
	}
	
	
	/**
	 *  halt()
	 *
	 *  This method halts the execution of the TM
	 *
	 */
	public void doHalt()
	{
		currentTM.halt();	
	}
	
	/**
	 *  reload()
	 *
	 *  This method reloads the current TM.
	 *
	 */
	public void reload()
	{
		gui.uncarat(currentTM.getTapeHeadPos());
		
		currentTM = backupTM;
		backupTM = currentTM.copy();
		
		gui.resetTape();
		gui.carat(currentTM.getTapeHeadPos());
		
		gui.tupleListTA.setText(" ");
		gui.statusBoxTA.setText(" ");
	}

	public StringBuffer printSerialNumber()
	{
		return currentTM.makeSerialNumber();	
	}
	
	/**
	 *  updateStausBox()
	 *
	 *  This method tells the user just what the TM is doing
	 *
	 *  @param currentTuple: the current 5Tuple we are printing out.
	 *
	 */
	public void updateStatusBox(TED5tuple currentTuple)
	{
		gui.updateStatusBox(currentTuple);
	}
	
	/**
	 *  updateTape
	 *
	 *  This method tells the Gui to update the tape and gives it the current position
	 *  of the tapehead.
	 *
	 *  @param x: the current position of the tapehead.
	 *
	 */
	public void updateTape(int x) 
	{
		gui.updateTape(x);
	}
	
	public void updateStepDisplay(int step)
	{
		gui.updateStepDisplay(step);	
	}	

	/**
	 *  updateRuleDisplay()
	 *
	 *  This method tells the gui to update the tuple history
	 *
	 *  @param tuple: the current 5Tuple we are printing out.
	 *
	 */
	public void updateRuleDisplay(String tuple)
	{
		gui.updateRuleDisplay(tuple);	
	}	
}	