// 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.*;


/**
 * class that implements the menu driven system that drives the applet
 */
class MainMenu extends JPanel implements ActionListener, Constants {

    // ---------------------------------------------------    
    //
    // declare global variables
    //
    // ---------------------------------------------------    

    // creates a fram to manipulate the configuration options
    //
    public JFrame config = null;

    // textfields and labels for the connector properties
    //
    public JLabel nameLabel = null;
    public JTextField nameField = null;
    
    // declare a reference to the DiGraph
    //
    public DiGraph digraph = null;

    // menu that holds all functionality
    //
    public JMenu menu = null;
    public JMenu subMenu = null;
    public JMenu subSubMenu = null;
    public JMenuBar menuBar = null;
    public JMenuItem menuItem = null;

    // declare a frame to display the help message
    //
    JFrame helpFrame = null;

    // declare a text area to display documentation
    //
    public JTextArea textArea = null;
    
    // declare a scrollable pane for the text area
    //
    public JScrollPane scrollPane = null;

    // declare the layout manager
    //
    public GridBagLayout gridbag = new GridBagLayout();
    
    // ---------------------------------------------------        
    //
    // declare class constructors
    //
    // ---------------------------------------------------    
   
    /**
     * The default constructor
     *
     * @param diGraph_a Digraph object to be initialized
     */
    public MainMenu(DiGraph diGraph_a) {
	
	super();

	// set the default layout
	//
	setLayout(gridbag);

	// set the reference to vertex box
	//
	digraph = diGraph_a;

	// instantiate the frame
	//
	helpFrame = new JFrame("Help");

	// instantiate the text area to display documentation
	//
	textArea = new JTextArea();
	textArea.setLineWrap(true);
	textArea.setWrapStyleWord(true);
	textArea.setEditable(false);
	
	// instantiate the scrollable pane for the text area
	//
	scrollPane = new JScrollPane(textArea);

	// set the scroll pane dismensions
	//
	scrollPane.setSize(new Dimension(HELP_WIDTH, HELP_HEIGHT));
	scrollPane.setPreferredSize(new Dimension(HELP_WIDTH, HELP_HEIGHT));
	scrollPane.setMinimumSize(new Dimension(HELP_WIDTH, HELP_HEIGHT));
	scrollPane.setMaximumSize(new Dimension(HELP_WIDTH, HELP_HEIGHT));

	// initialize the menu bar
	//
	menuBar = new JMenuBar();

	// create the file menu
	//	
	menu = new JMenu(fileStr);
	menu.setFont(newFont);
	menuBar.add(menu);

	// add the menu items
	//
	menuItem = new JMenuItem(clearStr);
	menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 
						       ActionEvent.ALT_MASK));
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(clearStr);
	menu.add(menuItem);

	menuItem = new JMenuItem(openStr);
	menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, 
						       ActionEvent.CTRL_MASK));
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(openStr);
	menu.add(menuItem);

	menuItem = new JMenuItem(saveStr);
	menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, 
						       ActionEvent.CTRL_MASK));
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(saveStr);
	menu.add(menuItem);

	menuItem = new JMenuItem(saveAsStr);
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(saveAsStr);
	menu.add(menuItem);

	menu.addSeparator();

	menuItem = new JMenuItem(quitStr);
	menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 
						       ActionEvent.ALT_MASK));
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(quitStr);
	menu.add(menuItem);

	// create the edit menu
	//
	menu = new JMenu(editStr);
	menu.setFont(newFont);
	menuBar.add(menu);

	menuItem = new JMenuItem(cutStr);
	menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, 
						       ActionEvent.CTRL_MASK));
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(cutStr);
	menu.add(menuItem);

	menuItem = new JMenuItem(copyStr);
	menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, 
						       ActionEvent.CTRL_MASK));
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(copyStr);
	menu.add(menuItem);

	menuItem = new JMenuItem(pasteStr);
	menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, 
						       ActionEvent.CTRL_MASK));
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(pasteStr);
	menu.add(menuItem);

	menu.addSeparator();

	menuItem = new JMenuItem(insArcStr);
	menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, 
						       ActionEvent.ALT_MASK));
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(insArcStr);
	menu.add(menuItem);

	menu.addSeparator();

	menuItem = new JMenuItem(delArcStr);
	menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, 
						       ActionEvent.ALT_MASK));
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(delArcStr);
	menu.add(menuItem);

	menuItem = new JMenuItem(delBlkStr);
	menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, 
						       ActionEvent.ALT_MASK));
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(delBlkStr);
	menu.add(menuItem);

	// create the algorithms menu
	//
	menu = new JMenu(compStr);
	menu.setFont(newFont);
	menuBar.add(menu);
	
	menu.addSeparator();
	
	String coeffLabel = null;
	String connection = null;
	String outputConfig = null;
	String inputConfig = null;

	int index = digraph.data.association.indexOf(TRANSFORM_TAG);	
	Vector algorithms = (Vector)digraph.data.values.elementAt(index);
	
	for (int i=0; i < algorithms.size(); i++) {
	    String algo = (String)algorithms.elementAt(i);
	    if(algo.equals("AudioFrontEnd"))
		{
		    inputConfig = "Input";
		    continue;
		}
	    if(algo.equals("Output"))
		{
		    outputConfig = algo;
		    break;
		}
	}

	menuItem = new JMenuItem(inputConfig);
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand("AudioFrontEnd");
	menu.add(menuItem);

	menuItem = new JMenuItem(outputConfig);
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand("Output");
	menu.add(menuItem);

	menu.addSeparator();

	for (int i=0; i < algorithms.size(); i++) {
	    String algo = (String)algorithms.elementAt(i);
	    
	    if(algo.equals("AudioFrontEnd"))
		{
		    continue;
		}   
	    if(algo.equals("Output"))
		{		
		    continue;
		}

	    if(algo.equals("CoefficientLabel"))
		{
		    coeffLabel = algo;
		    continue;
		}
	    if(algo.equals("Connection"))
		{
		    connection = algo;
		    continue;
		}	
	    menuItem = new JMenuItem(algo);
	    menuItem.setFont(newFont);
	    menuItem.addActionListener(this);
	    menuItem.setActionCommand(algo);
	    menu.add(menuItem);   
	}

	menu.addSeparator();

			
	menuItem = new JMenuItem(coeffLabel);
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(coeffLabel);
	menu.add(menuItem);   

	menuItem = new JMenuItem(connection);
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(connection);
	menu.add(menuItem);   

	menu.addSeparator();

	menuItem = new JMenuItem(contStr);
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(contStr);
	menu.add(menuItem);
	
	// create the help menu
	//
	menu = new JMenu(helpStr);
	menu.setFont(newFont);
	menuBar.add(Box.createHorizontalGlue());
	menuBar.add(menu);

	menuItem = new JMenuItem(overviewStr);
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(overviewStr);
	menu.add(menuItem);

	menu.addSeparator();

	menuItem = new JMenuItem(tutorialStr);
	menuItem.setFont(newFont);
	menuItem.addActionListener(this);
	menuItem.setActionCommand(tutorialStr);
	menu.add(menuItem);

	// set the dimensions of the menu
	//
	this.setSize(new Dimension(digraph.MAX_WIDTH, 30));
	this.setMinimumSize(new Dimension(digraph.MAX_WIDTH, 30));
	this.setMaximumSize(new Dimension(digraph.MAX_WIDTH, 30));
	this.setPreferredSize(new Dimension(digraph.MAX_WIDTH, 30));
    }
    
    // ---------------------------------------------------
    //
    // declare class methods
    //
    // ---------------------------------------------------
    
    /**
     * adds components to the control panel
     */
    public void add_components () {
	
	constrain(this, menuBar, 0, 0, 
		  GridBagConstraints.REMAINDER, GridBagConstraints.REMAINDER,
		  GridBagConstraints.BOTH, GridBagConstraints.CENTER,
		  1, 1, 0, 0, 0, 0);
    }

    /**
     * method listens for actions taking place on text only menu items
     *
     * @param e action command that is fired
     */
    public void actionPerformed(ActionEvent e) {

	//System.out.print("MainMenu action:  ");

	// get the source of the action that just occured
	//
	String source = e.getActionCommand();

	//System.out.println(source);

	// depending on the source of the event take the appropriate action
	//
	if(source.equals(openStr)) {
	    
	    JFileChooser loadChooser=null;
	    
	    if(digraph.paramFile != null) {
		loadChooser = new JFileChooser(digraph.paramFile);
	    }
	    else {
		String cwd = System.getProperty("user.dir");
	        loadChooser = new JFileChooser(cwd);
	    }

	    // set the font and button text for the load chooser
	    //
	    loadChooser.setFont(newFont);
	    String loadApprove = new String("Load");
	    loadChooser.setApproveButtonText(loadApprove);
	    
	    
	    // display the file chooser object
	    //
	    int returnVal = loadChooser.showOpenDialog(digraph);
	    
	    // check to see if a file was selected by the user
	    //
	    if (returnVal == JFileChooser.APPROVE_OPTION) {
		
		// retrieve the selected file
		//
		digraph.paramFile = loadChooser.getSelectedFile();
		
		// read the parameters to file
		//
		digraph.read();
	    } 

	} else if(source.equals(saveStr)) {

	    // write the parameters to file
	    //
	    if (digraph.paramFile != null) {
		digraph.write();
	    }
	    else {

		// initialize the file chooser object
		//
		String cwd = System.getProperty("user.dir");

		JFileChooser saveChooser = new JFileChooser(cwd);
		
		// set the font and button text for the save chooser
		//
		saveChooser.setFont(newFont);
		String saveApprove = new String("Save");
		saveChooser.setApproveButtonText(saveApprove);
		
		// display the file chooser object
		//
		int returnVal = saveChooser.showOpenDialog(digraph);
		
		// check to see if a file was selected by the user
		//
		if (returnVal == JFileChooser.APPROVE_OPTION) {
		    
		    // retrieve the selected file
		    //
		    digraph.paramFile = saveChooser.getSelectedFile();
		    
		    // write the parameters to file
		    //
		    digraph.write();
		}
	    }

	} else if(source.equals(saveAsStr)) {
	    
	    JFileChooser saveChooser = null;
	    
	    // initialize the file chooser object
	    //
	    if(digraph.paramFile != null) {
		saveChooser = new JFileChooser(digraph.paramFile);
	    }
	    else {
		String cwd = System.getProperty("user.dir");
		saveChooser = new JFileChooser(cwd);
	    }    
	    
	    // set the font and button text for the save chooser
	    //
	    saveChooser.setFont(newFont);
	    String saveApprove = new String("Save");
	    saveChooser.setApproveButtonText(saveApprove);
	    
	    // display the file chooser object
	    //
	    int returnVal = saveChooser.showOpenDialog(digraph);
	    
	    // check to see if a file was selected by the user
	    //
	    if (returnVal == JFileChooser.APPROVE_OPTION) {
		
		// retrieve the selected file
		//
		digraph.paramFile = saveChooser.getSelectedFile();
		
		// write the parameters to file
		//
		digraph.write();
	    } 

	} else if(source.equals(in_Config_Str)) {

	    // create and display the configuration panel
	    //
	    ConfigBoxIn systemInConfig = new ConfigBoxIn(digraph, digraph.data, digraph.inVertex, digraph.workArea, 0);
	    systemInConfig.pack();
	    systemInConfig.setVisible(true);

	    System.out.println("MainMenu in_config_str");

	} else if(source.equals(clearStr)) {

	    // reset the param file name
	    //
	    digraph.paramFile = null;

	    // clear out all existing memory
	    //
	    digraph.clearAllMemory();

	    // refresh the work area
	    //
	    digraph.workArea.repaint();

	} else if(source.equals(quitStr)) {

	    // exit without saving if nothing has changed
	    //
	    if (!digraph.saveWork) {
		System.exit(0);
	    }

	    // popup a dialogue that prompts the user to save his/her changes
	    //
	    JFrame frame = new JFrame("Warning");
	    int ans = JOptionPane.showConfirmDialog(frame, "Would you like to save your current changes?", "Warning", JOptionPane.YES_NO_CANCEL_OPTION);

	    // get the users choice
	    //
	    if (ans == JOptionPane.YES_OPTION) {

		// initialize the file chooser object
		//
		JFileChooser saveChooser = new JFileChooser();
		
		// set the font and button text for the save chooser
		//
		saveChooser.setFont(newFont);
		String saveApprove = new String("Save");
		saveChooser.setApproveButtonText(saveApprove);
		
		// display the file chooser object
		//
		int returnVal = saveChooser.showOpenDialog(digraph);
		
		// check to see if a file was selected by the user
		//
		if (returnVal == JFileChooser.APPROVE_OPTION) {
		    
		    // retrieve the selected file
		    //
		    digraph.paramFile = saveChooser.getSelectedFile();
		    
		    // write the parameters to file
		    //
		    digraph.write();
		}

		// close the application
		//
		System.exit(0);
	    }
	    
	    else if (ans == JOptionPane.NO_OPTION) {

		// close the application
		//
		System.exit(0);
	    }
	    
	    else {
		return;
	    }

	} else if (source.equals(updateStr)) {

	    // check to see if a vertex with this label exists
	    //
	    if (digraph.coeffLabels.contains(nameField.getText())) {

		// display a warning message indicating that you cannot have
		// two vertices with the same name
		//
		JFrame frame = new JFrame("Warning");
		JOptionPane.showMessageDialog(frame, "A node with the label " 
					      + nameField.getText() + 
					      " already exists");
		return;
	    }

	    // remove the old label from the vector
	    //
	    digraph.coeffLabels.remove(digraph.currVertexFocus.getText());
	    digraph.coeffLabels.addElement(nameField.getText());

	    // update the vertex text with what the user entered
	    //
	    digraph.currVertexFocus.setText(nameField.getText());

	    // remove the frame from the screen
	    //
	    config.setVisible(false);

	} else if (source.equals(cancelStr)) {

	    // remove the frame from the screen
	    //
	    config.setVisible(false);

	} else if(source.equals(overviewStr)) {

	    // create a dismiss button for the text area
	    //
	    JButton dismiss = new JButton(dismissStr);
	    dismiss.setActionCommand(dismissStr);
	    dismiss.addActionListener(this);

	    // read the help file contents and append them to the text area
	    //
	    try { 

		// clear the text area
		//
		textArea.setText("");

		// create a file object for I/O
		//
		File helpFile = new File(OVERVIEW_FILE);

		// create a file reader object
		//
		FileReader fileReader = new  FileReader(helpFile);

		// initialize the buffer to read the contents of the help file
		//
		BufferedReader buff = new BufferedReader(fileReader); 

		// read each line fo the file
		//
		String document;
		while((document = buff.readLine()) != null) { 

		    // add the help message line to the text area
		    //
		    textArea.append(document+newline);
		}
	    } 
	    catch(IOException ioe) { }

	    // add the components to the frame
	    //
	    helpFrame.getContentPane().add(scrollPane, BorderLayout.CENTER);
	    helpFrame.getContentPane().add(dismiss, BorderLayout.SOUTH);

            // display the text area and dismiss button
            //
            helpFrame.pack();
            helpFrame.setVisible(true);

	} else if(source.equals(tutorialStr)) {

	    // create a dismiss button for the text area
	    //
	    JButton dismiss = new JButton(dismissStr);
	    dismiss.setActionCommand(dismissStr);
	    dismiss.addActionListener(this);

	    // read the help file contents and append them to the text area
	    //
	    try { 

		// clear the text area
		//
		textArea.setText("");

		// create a file object for I/O
		//
		File helpFile = new File(TUTORIAL_FILE);

		// create a file reader object
		//
		FileReader fileReader = new  FileReader(helpFile);

		// initialize the buffer to read the contents of the help file
		//
		BufferedReader buff = new BufferedReader(fileReader); 

		// read each line fo the file
		//
		String document;
		while((document = buff.readLine()) != null) { 

		    // add the help message line to the text area
		    //
		    textArea.append(document+newline);
		}
	    } 
	    catch(IOException ioe) { }

	    // add the components to the frame
	    //
	    helpFrame.getContentPane().add(scrollPane, BorderLayout.CENTER);
	    helpFrame.getContentPane().add(dismiss, BorderLayout.SOUTH);

            // display the text area and dismiss button
            //
            helpFrame.pack();
            helpFrame.setVisible(true);

	} else if(source.equals(dismissStr)) {

	    // remove the frame form the screen
	    //
	    helpFrame.setVisible(false);

	} else if(source.equals(delBlkStr)) {

	    digraph.enableCompDeletion = true;

	    /*

	    // remove all children and parent edges
	    //
	    if (digraph.currVertexFocus != null) {
		if (digraph.currVertexFocus.getClass().getName().equals("Vertex")) {
		    digraph.removeVertex(digraph.currVertexFocus);
		}
	    }
	    */

	} else if(source.equals(cutStr)) {
	    digraph.cut();
	} else if(source.equals(copyStr)) {
	    digraph.copy();
	} else if(source.equals(pasteStr)) {
	    digraph.paste();
	} else if(source.equals(contStr)) {
	    if (digraph.vertices.size() > 0) {
		digraph.createIOData(CONTAINER, NONE);
	    }
	} else if(source.equals(insArcStr)) {
	    digraph.enableArcInsertion = true;
	} else if(source.equals(delArcStr)) {
	    digraph.enableArcDeletion = true;
	} else if(source.equals(tutorialStr)) {
	    // not yet implemented
	} else {
	    digraph.createAlgorithm(source);
	}
    }

    /**
     * this method creates the constraints of a component in a container
     * and then adds the component to the container.  it is based on 
     * code from "Java in a Nutshell" by David Flanagan. published by
     * O'Reilly and Associates incorporated.
     * 
     * @param container   container to place the component
     * @param component   the component to be constrained
     * @param grid_x      horizontal position of component
     * @param grid_y      vertical position of component
     * @param grid_width  number of horizontal grid spots to take
     * @param grid_height number of vertical grid spots to take
     * @param fill        directions to fill when component space is resized
     * @param anchor      anchor position when component space is resized
     * @param weight_x    relative amount of horizontal space 
     *                    component should take when its space is resized
     * @param weight_y    relative amount of vertical space component
     *                    should take when its space is resized
     * @param top         amount of inset space on top
     * @param left        amount of inset space on left
     * @param bottom      amount of inset space on bottom
     * @param right       amount of inset space on right
     * @return true
     */ 
    public boolean constrain(Container container, Component component, 
			     int grid_x, int grid_y, int grid_width, 
			     int grid_height, int fill, int anchor, 
			     double weight_x, double weight_y, int top,
			     int left, int bottom, int right) {
	
	// set the constraints based on the input variables
	//
	GridBagConstraints c = new GridBagConstraints();
	c.gridx = grid_x;
	c.gridy = grid_y;
	c.gridwidth = grid_width;
	c.gridheight = grid_height;
	c.fill = fill;
	c.anchor = anchor;
	c.weightx = weight_x;
	c.weighty = weight_y;
	
	// if any of the buffer insets are greater than zero, create a new
	// Insets object
	//
	if (top + bottom + left + right > 0)
	    c.insets = new Insets(top, left, bottom, right);
	
	// set the constraints of the component
	//
	((GridBagLayout) container.getLayout()).setConstraints(component, c);
	
	// add the component to the container
	//
	container.add(component);
	
	// exit gracefully
	//
	return true;
    }
}

//
// end of file





