// file: MainMenu.java
//

// import necessary java libraries
//
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.applet.*;

public class MainWindow extends JFrame implements Constants {
    
    // permanent file to be written to
    //
    public File paramFile = null;
    
    // flag to indicate whether a save is needed
    //
    boolean saveWork = false;

    // main menu for functionality
    //
    public MainMenu mainMenu = null;
	
    // data object to store data parsed from resource file
    //
    public Data data = null;
    
    // parser object to read resource file
    //
    public Parser parser = null;
   
    // vertex which will cause ConfigBox to find and build
    // recognizer (association) menu for the main window.
    //
    public Vertex vertex = null;


    // JPanel in place of the workarea to be passed to the ConfigBox
    // constructor
    JPanel cfg_panel = null;

    // here we go! a config box.
    //
    ConfigBox config_box = null;

    // this must:
    // use the parser to populate data
    // populate a vertex
    // create and add a config box to the JFrame. will be dialog to start,
    // but that can perhaps be changed to a panel for the recognizer
    // association, and the Dialog for all subwindows.
    public MainWindow(String title) {
	
	// call the parent constructor
	//
	super(title);
	
	// initialize save flag
	// 
	saveWork = false;

	// JPanel in place of the workarea to be passed to the ConfigBox
	// constructor
	cfg_panel = new JPanel();
	
	//instantiate the data class
	//
	data = new Data();
	
	// run the parser
	//
	parser = new Parser(data);

	// create the menu to control functionality
	//
	//	mainMenu = new MainMenu(this);

	// *** vertex initialization block.
	// create and initialize input configuration vertex
	//
	vertex = new Vertex("system", ALGORITHM, NONE);
	vertex.association = "RecognizeBuilder";

	// to simplify the creation, the data vectors will be trimmed to
	// only include the transform we're looking at and saved into
	// these three vectors for use in a bit
	//
	//	Vector labels2 = new Vector(5,5);
	//	Vector types2 = new Vector(5,5);
	//	Vector values2 = new Vector(5,5);
	
	//	for(int j=data.association.indexOf(vertex.association); 
	//   j <= data.association.lastIndexOf(vertex.association);
	//    j++) {
	//   if(j != -1) {
	//	labels2.add(data.name.get(j));
	//types2.add(data.type.get(j));
	//values2.add(data.values.get(j));
	//  }
	//	}	

	// initialize the vertex to the default values for its type
	// *** poorly coded. why should a vertex pass itself its own 
	// association? What's the point?
	//
	
	//	vertex.initializeConfig(labels2, values2, types2,
	//		vertex.association, data);
	//** end vertex initialization block

	//mainPane = new JPanel();

	// add panel to JFrame
	//
	//this.setContentPane(mainPane);	

	config_box = new ConfigBox(this, data, vertex, cfg_panel, 0);
	config_box.isRecognizer = true;
    }

    // method: write
    //
    // arguments: none
    // return   : none
    //
    // writes the sof file
    //
    public void write() {// declare local variables
	//
	FileOutputStream fout = null;
	PrintWriter file = null;
	String line = null;

	// reset the save flag to indicate the obvious
	//
	saveWork = false;

	// open the selected file for writing
	//
	try {  
	    // initialize the variables
	    //
	    line = new String();

	    // initialize the file output stream
	    //
	    fout = new FileOutputStream(paramFile);
	    file = new PrintWriter(fout);

	    // write the file header
	    //
	    file.println(HEADER_TAG_00);
	    file.println(HEADER_TAG_01);
	    file.println();

	    // begin writing specific code here.
	
	    // loop over all vertices?
	    //
	    // for(int i=0; i < vertex.names.size(); i++) {
	    for(int i = 0; i < config_box.labels.size(); i++) {
		// these work
		//	String type = (String)(vertex.types.get(i));
		//	String name = (String)(vertex.names.get(i));
		
		// these are theoretical
		String type = (String)(config_box.blockType.get(i));
		String name = (String)(config_box.labels.get(i));

		// add quotes to enum and text types. does not add quotes
		// to ints, floats, etc. 
		// *** need a seperate block for text field types. 
		if (type.equals("enum")) {
		    // clean up any white space
		    // *** necessary?
		    //
		    String text = (String)((JComboBox)config_box.enteredData.get(i)).getSelectedItem();
		    // add quotation marks
		    //
		    if(!text.equals("")) {
			file.println(vertex.names.get(i)
				     + " = \"" + text + "\";");
		    }
		}		    
		else if(type.equals("file")) {
		    
		    // use enteredData(i) to access the file button(s)
		    //
		    String text = ((JButton)config_box.enteredData.get(i)).getText();  
		    // add quotation marks
		    //
		    if(!text.equals("")) {
			file.println(vertex.names.get(i)
				     + " = \"" + text + "\";");
		    }
		}
		else { // all textfield types
		    String text =((JTextField)config_box.enteredData.get(i)).getText();  
		    if(!text.equals("")) {
			file.println(vertex.names.get(i)
				     + " = " + text + ";");
		    }
		}
	    }
	    
	    // end of specific code
	    file.close();
	}
	// catch and deal with any file I/O exceptions
	//
	catch(IOException e1) {}
    }

    // method: read
    //
    // arguments: none
    // return   : none
    //
    // writes the sof file
    //
    public void read() {
	
	// read in tokens from file. access vertex of main window, which 
	// has already been initialized from resource file. 
	// 
	// need access to the vectors of enumerated data which will become 
	// comboboxes. add associations to names vector, use decision structure
	// to assign appropriate type, add values to values vector.
	// give the modified vertex-vectors. re-assign config_box (old box will
	// be garbage collected) to a new ConfigBox with the now-updated vertex
	// - vectors. This will build the window, but how to set defaults?
	// assign newly parsed values to the FIRST element in the enum vectors.
	// this will make them default. 

	String line = null;
	FileReader fin = null;
	BufferedReader file = null;
	StringTokenizer tokens = null;
	int line_index = 0;
	
	// open the selected file for writing
	//
	try {
	    
	    // initialize the file output stream
	    //	
	    fin = new FileReader(paramFile);
	    file = new BufferedReader(fin);
	    
	    // read the lines from the file
	    //
	    //  try {
	    // need io error handlers!
	    // remove white spaces at the ends of the string
	    // read the sof tag
	    //
	    if((line = file.readLine()) != null) {
		line = line.trim();
		line_index++;
	    }

	    // remove white spaces at the ends of the string
	    // *** read the hmm (or?) tag. exit if eof
	    //
	    if((line = file.readLine()) != null) {
		line = line.trim();
		line_index++;
	    }	    
	    // mark the current position in the buffer stream
	    //
	    file.mark(100);
	    
	    // read the rest of the data for the object
	    //
	    while ((line = file.readLine()) != null) {
		
		line_index++;

		// variable to store the type of the parameter
		//	    
		String type = null;
		
		// variable to store the value of the parameter
		//
		String val = null; 
		
		// remove leading and trailing white space letters
		//
		line = line.trim();
		
		// divide the line into left and right of equals operator
		//
		tokens = new StringTokenizer(line, "=");
		
		// parse the association
		//
		String assoc = "" + tokens.nextToken();
		
		// trim any white space from the assoc
		//
		assoc = assoc.trim();
		
		// will parse the value
		//
		if (tokens.hasMoreTokens()) {
		    
		    // remove any semicolons and white space from
		    // val
		    //
		    val = "" + tokens.nextToken();
		    val = val.replace(';', ' ');   
		    val = val.trim();
		}
		
		// get the index of the assoc within the list of names
		//
		int index =(config_box.labels).indexOf(assoc);
		
		// if the assoc was found
		//
		if (index != -1) {
		    
		    // get the type of the parameter
		    //
		    type = (String)config_box.types.get(index);
		    
		    // if the assoc was found in the list of names, then a valid
		    // component type will be found, and the " marks will be taken
		    // care of within config_box, so remove any that are already
		    // present.
		    //
		    val = val.replace('\"',' ');
		    
		    if(type == "enum") {
				    
			// remove value from the list of enumerated values stored 
			// at value.get(i), and insert the value at the beginning
			// of the enum list, so that the combobox will use it as
			// the default value.
			//
			((Vector)config_box.values.get(index)).remove(val);
			((Vector)config_box.values.get(index)).insertElementAt(val, 0);
		    }
		    else { // not enum, just change the value
			((Vector)config_box.values.get(index)).setElementAt(val, 0);
		    }
		} 
		else { 
		    // just use a textField type, and leave the quotes.
		    // if they are present, they will still need to 
		    // be present when the parameter is written again.
		    // *** can use a flag to remove the possibility of 
		    // human error- removing of quotes from text box
		    //
		    config_box.labels.add(assoc);
		    config_box.types.add("text");
		    config_box.values.add(val);
		}
		
		// turn off old config box
		config_box.setVisible(false);
		config_box.isRecognizer = false;
		config_box.dispose();

		// turn on new config box
		//
		config_box = new ConfigBox(this, data, vertex, cfg_panel, 0);
		
		//*** will need to be changed for sub-window support
		//
		config_box.isRecognizer = true;
		
		

		// ? need to mark position of file?
	    } // end of looping over lines
	    
	    // close the file 
	    //
	    file.close();

	}// end of try block

	catch(IOException e) {
	    System.err.println();
	    System.err.println("---------------------------------------");
	    System.err.println("Caught IOException: " + e.getMessage());
	    System.err.println("Line Number: " + line_index);
	    System.err.println("File Line: " + line);
	    System.err.println("---------------------------------------");
	    System.exit(0);
	}
	catch(ArrayIndexOutOfBoundsException e) {
	    System.err.println();
	    System.err.println("---------------------------------------");
	    System.err.println("Caught ArrayIndexOutOfBoundsException:2 " + e.getMessage());
	    System.err.println("Line Number: " + line_index);
	    System.err.println("File Line: " + line);
	    System.err.println("---------------------------------------");
	    System.exit(0);
	}
	catch(NullPointerException e) {
	    System.err.println();
	    System.err.println("---------------------------------------");
	    System.err.println("Caught NullPointerException: " + e.getMessage());
	    System.err.println("Line Number: " + line_index);
	    System.err.println("File Line: " + line);
	    System.err.println("---------------------------------------");
	    System.exit(0);
	}	
	catch(Exception e) {
	    System.err.println();
	    System.err.println("---------------------------------------");
	    System.err.println("Caught Exception: " + e.getMessage());
	    System.err.println("Line Number: " + line_index);
	    System.err.println("File Line: " + line);
	    System.err.println("---------------------------------------");
	    System.exit(0);
	}
    }// end of read function
}









