import java.awt.*;
import java.util.*;
import java.io.*;

public class UI extends Frame {
	

	public final static int STANDARD_PARSE = 0;

	public final static int TOKEN_LIST = 1;

 	

	String current_source_name;
	String current_source_path;
	String current_config_name;
	String current_config_path;
	
	String original_code;
	String updated_code;

	
	// Standard AWT initializers

	MenuBar menubar = new MenuBar();
	Menu file_menu = new Menu("File");
	Menu window_menu = new Menu("Windows");
	Menu help_menu = new Menu("Help");
	
	MenuItem save_source_item, save_source_as_item, save_config_item, save_config_as_item, revert;
	
	Panel Header_Panel = new Panel();
	Panel Main_Panel = new Panel();
	
	Panel Left_Header_Panel = new Panel();
	Panel Right_Header_Panel = new Panel();
	
	Panel Settings_Panel = new Panel();
	Panel Output_Panel = new Panel();
	Panel Controls_Panel = new Panel();
	Panel Settings_Sets = new Panel();
	Panel Settings_Buttons1 = new Panel();
	Panel Settings_Buttons2 = new Panel();
	Panel Settings_Buttons3 = new Panel();
	
	TextArea textarea = new TextArea(20,90);
	TextField source_field = new TextField("The Current File", 20);
	TextField config_field = new TextField("The Current Configuration", 20);
	TextField output_field = new TextField(2);
	
	Label settings_label = new Label("Settings:", Label.CENTER);
	Label output_label = new Label("Output:", Label.CENTER);
	Label controls_label = new Label("Controls:", Label.CENTER);
	
	Label source_label = new Label("Current Source File:", Label.LEFT);
	Label config_label = new Label("Current Configuration:", Label.RIGHT);
	
	Checkbox op_space_box = new Checkbox("Space Around Operators?", null, true);
	Checkbox bracket_line_box = new Checkbox("Brackets on a new line?", null, false);
	Checkbox extra_line_box = new Checkbox("Extra Line Between Functions?", null, true);
	Checkbox live_update = new Checkbox("Update on the fly?", null, true);



	Choice parse_choice;

	

	Checkbox future1 = new Checkbox("Future Setting 1?", null, false);
	Checkbox future2 = new Checkbox("Future Setting 2?", null, false);
	Checkbox future3 = new Checkbox("Future Setting 3?", null, false);
	Checkbox future4 = new Checkbox("Future Setting 4?", null, false);
	Choice indent_choice;
	
	Button Update = new Button("Beautify");
	
	Button primary_settings = new Button("Primary Settings");
	Button performance_settings = new Button("Performance Settings");
	Button future_settings = new Button("Future Settings Group");
	
	public static Original Original_Frame = new Original("The Original Code");
	
	public Update_Module Update_Thing;



	public UI(String title) {
		
		super(title);


		setMenuBar(menubar);
		
		save_source_item = new MenuItem("Save Source File");
		save_source_as_item = new MenuItem("Save Source File As");
		save_config_item = new MenuItem("Save Configuration");
		save_config_as_item = new MenuItem("Save Configuration As");
		revert = new MenuItem("Revert to Saved");
		file_menu.add(new MenuItem("New Source File"));
		file_menu.add(new MenuItem("-"));
		file_menu.add(new MenuItem("Load Source File"));
		file_menu.add(save_source_item);
		file_menu.add(save_source_as_item);
		file_menu.add(new MenuItem("-"));
		file_menu.add(new MenuItem("Load Configuration"));
		file_menu.add(save_config_item);
		file_menu.add(save_config_as_item);
		file_menu.add(new MenuItem("-"));
		file_menu.add(revert);
		file_menu.add(new MenuItem("-"));
		file_menu.add(new MenuItem("Start Over"));
		file_menu.add(new MenuItem("-"));
		file_menu.add(new MenuItem("Exit"));
		
		window_menu.add(new MenuItem("Source Window"));
		
		help_menu.add(new MenuItem("About Beautify"));
		help_menu.add(new MenuItem("-"));
		help_menu.add(new MenuItem("Contents"));
		
		menubar.add(file_menu);
		menubar.add(window_menu);
		menubar.setHelpMenu(help_menu);
		
		indent_choice = new Choice();
		indent_choice.addItem("1 spaces");
		indent_choice.addItem("2 spaces");
		indent_choice.addItem("3 spaces");
		indent_choice.addItem("4 spaces");
		indent_choice.addItem("6 spaces");
		indent_choice.addItem("8 spaces");
		indent_choice.addItem("1 tab");
		indent_choice.addItem("2 tabs");
		indent_choice.select("4 spaces");
		
		parse_choice = new Choice();

		parse_choice.addItem("Standard Formatting");

		parse_choice.addItem("Token List");

		indent_choice.select("Standard Formatting");



		Settings_Buttons1.add(indent_choice);
		Settings_Buttons1.add(op_space_box);
		Settings_Buttons1.add(bracket_line_box);
		Settings_Buttons1.add(extra_line_box);
		Settings_Buttons2.add(live_update);

		Settings_Buttons2.add(parse_choice);

		Settings_Buttons2.add(future1);
		Settings_Buttons3.add(future2);
		Settings_Buttons3.add(future3);
		Settings_Buttons3.add(future4);
		
		Settings_Sets.setLayout(new FlowLayout(FlowLayout.CENTER));
		Settings_Sets.add(primary_settings);
		Settings_Sets.add(performance_settings);
		Settings_Sets.add(future_settings);
		
		Settings_Panel.setLayout(new BorderLayout());
		Settings_Panel.add("North", settings_label);
		Settings_Panel.add("Center", Settings_Sets);
		Settings_Panel.add("South", Settings_Buttons3);
		Settings_Panel.add("South", Settings_Buttons2);
		Settings_Panel.add("South", Settings_Buttons1);
		
		textarea.setFont(new Font("Courier", Font.PLAIN, 12));
		textarea.setEditable(false);
		
		Output_Panel.setLayout(new BorderLayout(10, 10));
		Output_Panel.add("North", output_label);
		Output_Panel.add("South", output_field);
		Output_Panel.add("Center", textarea);
		
		Controls_Panel.setLayout(new BorderLayout());
		Controls_Panel.add("North", controls_label);
		Controls_Panel.add("South", Update);
		
		Left_Header_Panel.setLayout(new BorderLayout());
		Left_Header_Panel.add("West", source_label);
		Left_Header_Panel.add("East", source_field);
		
		Right_Header_Panel.setLayout(new BorderLayout());
		Right_Header_Panel.add("West", config_label);
		Right_Header_Panel.add("East", config_field);
		
		Header_Panel.setLayout(new BorderLayout(10, 10));
		Header_Panel.add("West", Left_Header_Panel);
		Header_Panel.add("East", Right_Header_Panel);
		
		Main_Panel.setLayout(new BorderLayout(10, 10));
		
		Main_Panel.add("North", Settings_Panel);
		Main_Panel.add("South", Controls_Panel);
		Main_Panel.add("Center", Output_Panel);
		
		setLayout(new BorderLayout(10, 10));
		add("North", Header_Panel);
		add("Center", Main_Panel);
		
		settings_label.setFont(new Font("Times", 1, 18));
		output_label.setFont(new Font("Times", 1, 18));
		controls_label.setFont(new Font("Times", 1, 18));
		

	}



	public boolean action(Event evt, Object arg) {
		if (evt.target instanceof MenuItem) {
			if (arg == "New Source File") {
				// had to do a hide, then show, since MSDev does not handle

				// to front properly.

				Original_Frame.hide();
				Original_Frame.show();
				Original_Frame.setText("");
				output_field.setText("Blank source file");	
				UIEnable();
				current_source_name = "--null--";
				current_source_path = "--null--";
				source_field.setText("The Current File");
				original_code = "";
				updated_code = "";
				textarea.setText("");
				Original_Frame.setText("");
			} else if (arg == "Load Source File") {
				FileDialog fd = new FileDialog(this, "Load Source File", FileDialog.LOAD);
				fd.show();
				if (!(fd.getFile() == null)) {
					LoadSource(fd.getFile(), fd.getDirectory());
					// had to do a hide, then show, since MSDev does not handle

					// to front properly.

					Original_Frame.hide();
					Original_Frame.show();
					UIEnable();
					return true;
				}
			} else if (arg == "Save Source File") {
				if (current_source_name.equals("--null--")) {
					FileDialog fd = new FileDialog(this, "Save Source File As", FileDialog.SAVE);
					fd.show();
					if (!(fd.getFile() == null)) {
						// make sure that the file is there
						SaveSource(fd.getFile(), fd.getDirectory());
						updateCode();
					}
				} else {
					SaveSource(current_source_name, current_source_path);
				}				
				return true;
			} else if (arg == "Save Source File As") {
				FileDialog fd = new FileDialog(this, "Save Source File As", FileDialog.SAVE);
				fd.show();
				if (!(fd.getFile() == null)) {
					// make sure that the file is there
					SaveSource(fd.getFile(), fd.getDirectory());
					updateCode();
				}
				return true;
			} else if (arg == "Load Configuration") {
				FileDialog fd = new FileDialog(this, "Load Configuration", FileDialog.LOAD);
				fd.show();
				if (!(fd.getFile() == null)) {
					// make sure that the file is there
					LoadConfig(fd.getFile(), fd.getDirectory());
					return true;
				}
			} else if (arg == "Save Configuration") {
				if (current_config_name.equals("--null--")) {
					FileDialog fd = new FileDialog(this, "Save Configuration", FileDialog.SAVE);
					fd.show();
					if (!(fd.getFile() == null)) {
						// make sure that the file is there
						SaveConfig(fd.getFile(), fd.getDirectory());
						return true;
					}
				} else {
					SaveConfig(current_config_name, current_config_path);
				}
				return true;
			} else if (arg == "Save Configuration As") {
				FileDialog fd = new FileDialog(this, "Save Configuration", FileDialog.SAVE);
				fd.show();
				if (!(fd.getFile() == null)) {
					// make sure that the file is there
					SaveConfig(fd.getFile(), fd.getDirectory());
					return true;
				}
			} else if (arg == "Revert to Saved") {
				if (current_source_name.equals("--null--")) {
					output_field.setText("No file saved");
				} else {
					Original_Frame.setText(original_code);
					updateCode();
					output_field.setText("Revert to last saved: " + current_source_path + current_source_name);
					show();
				}
				return true;
			} else if (arg == "Start Over") {
				UIinit();
				return true;
			} else if (arg == "Exit") {
				dispose();
				Original_Frame.dispose();
				System.exit(0);
				return true;
			} else if (arg == "Source Window") {
				if (original_code == "") {
					output_field.setText("Blank source file");	
					UIEnable();
				}
				// had to do a hide, then show, since MSDev does not handle

				// to front properly.

				Original_Frame.hide();
				Original_Frame.show();
				return true;
			} else if (arg == "About Beautify") {

				About about_box = new About(this);

			}
		} else if (evt.target instanceof Button) {
			if (arg == "Beautify") {
				updateCode();
			// change the settings panels, a tab-type implementation

			} else if (arg == "Primary Settings") {
				Settings_Panel.getComponent(4).hide();
				Settings_Panel.add("South", Settings_Buttons1);
				Settings_Buttons1.show();
				Settings_Panel.show();
				show();
			} else if (arg == "Performance Settings") {
				Settings_Panel.getComponent(4).hide();
				Settings_Panel.add("South", Settings_Buttons2);
				Settings_Buttons2.show();
				Settings_Panel.show();
				show();
			} else if (arg == "Future Settings Group") {
				Settings_Panel.getComponent(4).hide();
				Settings_Panel.add("South", Settings_Buttons3);
				Settings_Buttons3.show();
				Settings_Panel.show();
				show();
			}
			return true;
		} else if (evt.target instanceof Checkbox || evt.target instanceof Choice) {

			if (live_update.getState()) {

				updateCode();

			}

		}
		return false;
	}

	public boolean handleEvent(Event evt) {
		// quits the app

		if (evt.id == Event.WINDOW_DESTROY) {
			hide();
			dispose();

			System.exit(0);

			return true;
		}
		return super.handleEvent(evt);
	}

	// clear and set all of the pertinent variables

	public void UIinit() {
		current_source_name = "--null--";
		current_source_path = "--null--";
		source_field.setText("The Current File");
		current_config_name = "--null--";
		current_config_path = "--null--";
		config_field.setText("The Current Configuration");
		original_code = "";
		updated_code = "";
		op_space_box.setState(true);
		bracket_line_box.setState(false);
		extra_line_box.setState(true);
		live_update.setState(true);
		future1.setState(false);
		future2.setState(false);
		future3.setState(false);
		future4.setState(false);
		indent_choice.select("4 spaces");
		textarea.setText("");
		Original_Frame.setText("");
		pack();
		show();
		output_field.setText("Please select a source file to format or a configuration file from the File Menu");	
		UIDisable();
	}

	// disable all of the pertinent variables to make sure you load a source first

	private void UIDisable() {
		indent_choice.disable();
		op_space_box.disable();
		bracket_line_box.disable();
		extra_line_box.disable();
		live_update.disable();
		future1.disable();
		future2.disable();
		future3.disable();
		future4.disable();
		Update.disable();
		save_source_item.disable();
		save_source_as_item.disable();
		save_config_item.disable();
		save_config_as_item.disable();
		revert.disable();
	}

	// enable all of the pertinent variables

	private void UIEnable() {
		indent_choice.enable();
		op_space_box.enable();
		bracket_line_box.enable();
		extra_line_box.enable();
		live_update.enable();
		future1.enable();
		future2.enable();
		future3.enable();
		future4.enable();
		Update.enable();
		if (!Beautify.isApplet) {

			save_source_item.enable();
			save_source_as_item.enable();
			save_config_item.enable();
			save_config_as_item.enable();
			revert.enable();
		}

	}

	private void LoadSource(String filename, String directory) {
		String filepath = new String(directory + filename);
		File worldfile = new File(filepath);
		FileInputStream fin = null;
		try { fin = new FileInputStream(worldfile); }
		catch (FileNotFoundException fnfe) {System.out.println("No find file");}
		current_source_name = filename;
		current_source_path = directory;
		source_field.setText(filename);
		DataInputStream in = new DataInputStream(fin);
		output_field.setText("Loading...");

		String tempstring = null;
		boolean DoneFile = false;
		original_code = "";
		while (!(DoneFile)) {
			try{tempstring = in.readLine();}
			catch(IOException ioe) {
				DoneFile = true;
			}
			if (tempstring != null) {
				original_code += (tempstring + "\n");
			} else {
				DoneFile = true;

			}
		}
		Original_Frame.setText(original_code);
		output_field.setText("Load Source File: " + filepath);
		updateCode();
		try{in.close();}
		catch (IOException e) {}
		try{fin.close();}
		catch (IOException e) {}
	}

	private void SaveSource(String filename, String directory) {
		updateCode();
		String filepath = new String(directory + filename);
		File worldfile = new File(filepath);
		FileOutputStream fon = null;
		try { fon = new FileOutputStream(worldfile); }
		catch (IOException fnfe) {}
		current_source_name = filename;
		current_source_path = directory;
		source_field.setText(filename);
		output_field.setText("Save Source File: " + filepath);
		DataOutputStream out = new DataOutputStream(fon);
		output_field.setText("Saving...");

		try{
			out.writeBytes(textarea.getText());
		}
		catch(IOException ioe) {}
		original_code = textarea.getText();
		Original_Frame.setText(original_code);
		output_field.setText("Save Source File: " + filepath);
		config_field.setText(filename);
		updateCode();
		try{out.close();}
		catch (IOException e) {}
		try{fon.close();}
		catch (IOException e) {}
	}

	private void LoadConfig(String filename, String directory) {
		String filepath = new String(directory + filename);
		File worldfile = new File(filepath);
		FileInputStream fin = null;
		try { fin = new FileInputStream(worldfile); }
		catch (FileNotFoundException fnfe) {System.out.println("No find file");}
		current_config_name = filename;
		current_config_path = directory;
		config_field.setText(filename);
		DataInputStream in = new DataInputStream(fin);
		output_field.setText("Loading...");

		String tempstring = null;
		String delim = "\t";
		boolean DoneFile = false;
		while (!(DoneFile)) {
			try{tempstring = in.readLine();}
			catch(IOException ioe) {
				DoneFile = true;
			}
			if (tempstring != null) {
				StringTokenizer token = new StringTokenizer(tempstring, delim);
				String argument = new String(token.nextToken());
				String value = new String(token.nextToken());
				argument = argument.toLowerCase();
				value = value.toLowerCase();
				if (argument.equals("indent_choice")) {
					indent_choice.select(value);
				} else if (argument.equals("opspace")) {
					op_space_box.setState((Boolean.valueOf(value)).booleanValue());
				} else if (argument.equals("brackline")) {
					bracket_line_box.setState((Boolean.valueOf(value)).booleanValue());
				} else if (argument.equals("extra_line_box")) {
					extra_line_box.setState((Boolean.valueOf(value)).booleanValue());
				} else if (argument.equals("live_update")) {
					live_update.setState((Boolean.valueOf(value)).booleanValue());
				} else if (argument.equals("future1")) {
					future1.setState((Boolean.valueOf(value)).booleanValue());
				} else if (argument.equals("future2")) {
					future2.setState((Boolean.valueOf(value)).booleanValue());
				} else if (argument.equals("future3")) {
					future3.setState((Boolean.valueOf(value)).booleanValue());
				} else if (argument.equals("future4")) {
					future4.setState((Boolean.valueOf(value)).booleanValue());
				}
			}  else {
				DoneFile = true;

			}
		}
		output_field.setText("Load Configuration File: " + filepath);
		updateCode();
		try{in.close();}
		catch (IOException e) {}
		try{fin.close();}
		catch (IOException e) {}
	}

	private void SaveConfig(String filename, String directory) {
		String filepath = new String(directory + filename);
		File worldfile = new File(filepath);
		FileOutputStream fon = null;
		try { fon = new FileOutputStream(worldfile); }
		catch (IOException fnfe) {
			output_field.setText("Invalid Name: Please use a .txt suffix");
			return;
		}
		current_config_name = filename;
		current_config_path = directory;
		DataOutputStream out = new DataOutputStream(fon);
		output_field.setText("Saving...");

		try{
			out.writeBytes("indent_choice\t" + indent_choice.getSelectedItem() + "\r");
			out.writeBytes("opspace\t" + String.valueOf(op_space_box.getState()) + "\r");
			out.writeBytes("brackline\t" + String.valueOf(bracket_line_box.getState()) + "\r");
			out.writeBytes("extra_line_box\t" + String.valueOf(extra_line_box.getState()) + "\r");
			out.writeBytes("live_update\t" + String.valueOf(live_update.getState()) + "\r");
			out.writeBytes("future1\t" + String.valueOf(future1.getState()) + "\r");
			out.writeBytes("future2\t" + String.valueOf(future2.getState()) + "\r");
			out.writeBytes("future3\t" + String.valueOf(future3.getState()) + "\r");
			out.writeBytes("future4\t" + String.valueOf(future4.getState()) + "\r");
		}
		catch(IOException ioe) {}
		output_field.setText("Save Configuration File: " + filepath);
		config_field.setText(filename);
		try{out.close();}
		catch (IOException e) {}
		try{fon.close();}
		catch (IOException e) {}
	}

	// calls the parser, and updates the text area with the new code.

	public void updateCode() {

		int parse_choice_int = STANDARD_PARSE;

		String input, indy = "";

		show();

		output_field.setText("Updating...");



		if (parse_choice.getSelectedItem() == "Standard Formatting") {

			parse_choice_int = STANDARD_PARSE;

		} else if (parse_choice.getSelectedItem() == "Token List") {

			parse_choice_int = TOKEN_LIST;

		}	



		input = indent_choice.getSelectedItem();



		if (input == "1 spaces") {

			indy = " ";

		} else if (input == "2 spaces") {

			indy =  "  ";

		} else if (input == "3 spaces") {

			indy =  "   ";

		} else if (input == "4 spaces") {

			indy =  "    ";

		} else if (input == "6 spaces") {

			indy =  "      ";

		} else if (input == "8 spaces") {

			indy =  "        ";

		} else if (input == "1 tab") {

			indy =  "\t";

		} else if (input == "2 tabs") {

			indy =  "\t\t";

		}

			



		Update_Thing = new Update_Module();



		/*   update prototype:

		 * updateCode(InputStream in_stream, 

		 *				int parse_choice,

		 *				boolean operator_space, 

		 *				boolean bracket_new_line, 

		 *				boolean extra_line, 

		 *				String indent)

		 */

		try {

//	1.1		updated_code = Update_Thing.updateCode(new StringReader(Original_Frame.getText()), 

			updated_code = Update_Thing.updateCode(new StringBufferInputStream(Original_Frame.getText()), 

							parse_choice_int, op_space_box.getState(), bracket_line_box.getState(), 

							extra_line_box.getState(), indy);

		}

		catch (IOException e) {

			System.out.println("an error occured in the update code function");

//			System.in.read();

		}



		textarea.setText(updated_code);

		output_field.setText("Updated Successfully");

	

	}





}