/*---------------------------------------------------------------------------
File:         			MainMenu.java
Package:                        JFLAP Version 3.1
Author:				Magda & Octavian Procopiuc V1.0 07/15/96
                                Eric Gramond V3.0 07/22/98
				Ted Hung V3.1 7/10/99
 
Description of Contents:	Contains class MainMenu.
				
--------------------------------------------------------------------------*/

/* 
 * Susan H. Rodger, Magda Procopiuc, Octavian Procopiuc, Eric Gramond, Ted Hung
 * Computer Science Department
 * Duke University
 * August 1999
 * Supported by National Science Foundation DUE-9596002, DUE-9555084,
 *  and DUE-9752583
 *
 * Copyright (c) 1999
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the author.  The name of the author may not be used to
 * endorse or promote products derived from this software without
 * specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

package flap;

import java.awt.*;
import java.util.*;
import java.io.*;
import java.awt.event.*;
import java.net.*;
import java.lang.reflect.*;

/**
 * The initial menu which enables the user to open
 * as many Environment windows as he/she wants
 * with the desired machine type. Basically,
 * it contains one button for each machine type
 * and an exit button.
 *
 * @see		flap.Environment
 * @author	Magda & Octavian Procopiuc
 * @version	1.0 15 July 1996
 */

public class MainMenu extends Frame implements ActionListener, WindowListener{
    
  Vector	windows = new Vector(1, 1);
  String	paramsFileName = ".flaprc";
  boolean	isApplet = false;
  
    /**
     * The Help Window
     */
  public HelpWindow myHelpWindow;
    

  static String STR_FSA = "Finite State Automaton";
  static String STR_PDA = "Pushdown Automaton";
  static String STR_1TM = "1-tape Turing Machine";
  static String STR_2TM = "2-tape Turing Machine";
  static String STR_GRA = "Grammar Conversion";
  static String STR_REX = "Regular Expression Conversion";
  static String STR_QUIT = "QUIT";

  public static String osName;
  public static String fileSeparator;
  public static String workingDirectory;
  
  public static final String OK_STR = "Ok";
  public static final String CANCEL_STR = "Cancel";
  public static final String[] OK_CANCEL_STR = {OK_STR, CANCEL_STR};

    static {
    if (workingDirectory == null)
      workingDirectory = "";
    else if (!workingDirectory.endsWith(fileSeparator))
      workingDirectory += fileSeparator;
  }
 
  public MainMenu() {}
 
  public MainMenu(String args[], boolean isApplet) {
    super("JFlap - Main Menu");
    this.isApplet = isApplet;
    this.addWindowListener(this);

    if(!isApplet) {
      osName = System.getProperty("os.name");
      fileSeparator = System.getProperty("file.separator");
      workingDirectory = System.getProperty("user.dir");
    }
   

    setLayout(new GridLayout(7, 1));
    Button c;
    Color color = Params._mm_backcolor;
    add(c = new Button(STR_FSA));
    c.setBackground(color);
    c.addActionListener(this);
    add(c = new Button(STR_PDA));
    c.setBackground(color);
    c.addActionListener(this);
    add(c = new Button(STR_1TM));
    c.setBackground(color);
    c.addActionListener(this);
    add(c = new Button(STR_2TM));
    c.setBackground(color);
    c.addActionListener(this);
    add(c = new Button(STR_GRA));
    c.setBackground(color);
    c.addActionListener(this);    
    add(c = new Button(STR_REX));
    c.setBackground(color);
    c.addActionListener(this);
    add(c = new Button(STR_QUIT));
    c.setBackground(color);
    c.addActionListener(this);

    pack();

    URL iconName = this.getClass().getResource(Params._mm_icon_name);
    Toolkit t = Toolkit.getDefaultToolkit();
    setIconImage(t.getImage(iconName));

    if (args != null)
      parseArgs(args);
  }

  public void windowClosing(WindowEvent e) 
  {
    startThread("quit");
  }
  public void windowOpened(WindowEvent e) 
  {}
  public void windowIconified(WindowEvent e) 
  {}
  public void windowDeiconified(WindowEvent e) 
  {}
  public void windowClosed(WindowEvent e)
  {}
  public void windowActivated(WindowEvent e) 
  {}
  public void windowDeactivated(WindowEvent e) 
  {}

  public void actionPerformed(ActionEvent e){
    Frame f;

    if(e.getActionCommand().equals(STR_QUIT)) 
	startThread("quit");
    else if(e.getActionCommand().equals(SourceWindow.STR_QUIT)) 
	startThread("quit"); 
    else if(e.getActionCommand().equals(STR_FSA)) {
	f = createEnvironment(Machine.FSA, Environment.NO_FILE_NAME);
	f.setVisible(true);
    }
    else if(e.getActionCommand().equals(STR_PDA)) {
	f = createEnvironment(Machine.PDA, Environment.NO_FILE_NAME);
	f.setVisible(true);
    }
    else if(e.getActionCommand().equals(STR_1TM)) {
	f = createEnvironment(Machine.TM1, Environment.NO_FILE_NAME);
	f.setVisible(true);	
    }
    else if(e.getActionCommand().equals(STR_2TM)) {
	f = createEnvironment(Machine.TM2, Environment.NO_FILE_NAME);
	f.setVisible(true);
    }
    else if(e.getActionCommand().equals(STR_GRA)) {
	f = createEnvironment(Machine.GRA, Environment.NO_FILE_NAME);
	f.setVisible(true);
    }
    else if(e.getActionCommand().equals(STR_REX)) {
	f = createEnvironment(Machine.REX, Environment.NO_FILE_NAME);
	f.setVisible(true);
    }    
    //window notifies that it has closed itself. closing handled by the window.
    else if(SourceWindow.STR_CLOSE.equals(e.getActionCommand())) {
	f = (Frame) e.getSource();	
        windows.removeElement(f);
    }
  }

  public Dimension getPreferredSize() {
    return new Dimension(Params._mm_width, Params._mm_height);
  }


    /* 
     * starts a function thread with the given function inside
     */
  public void  startThread(String functionName) {
	FunctionThread ft;
	Class source;
	try {
	    source = this.getClass();
	    ft = new FunctionThread(source.getMethod(functionName, new Class[0]), this, new Object[0]);
	    ft.start();
	}
	catch(NoSuchMethodException h) {
	    System.out.println("no " + functionName + " method found.");
	}
  }
   
  /**
   * Checks if the user wants to save all the unsaved machines and
   * exits if the user didn't cancel the operation.
   */
    public void quit() {
	int i = 0;
	SourceWindow sw;
	boolean b;
	setEnabled(false);
	while (i < windows.size()) {
	    sw = (SourceWindow) windows.elementAt(i);
	    b = sw.isEnabled();
	    sw.setEnabled(false);
	    sw.show();
	    if (!sw.quit()) {
		sw.setEnabled(b);
		setEnabled(true);
		return;
	    }
	}
	setVisible(false);
	System.exit(0);
    }

  /**
   * Parses the command line arguments.
   */
  void parseArgs(String args[]) {
    int		i = 0;
    String	arg;
    String	fileName = Environment.NO_FILE_NAME;

    while (i < args.length) {
      if (args[i].startsWith("-")) {
        arg = args[i++];
        if (i == 1) {
          if (arg.equalsIgnoreCase("-p"))
            if (i < args.length)
              if (!args[i].startsWith("-"))
                paramsFileName = args[i++];
          readParams();
        }
        if (i < args.length)
          if (!args[i].startsWith("-"))
            fileName = args[i++];
        if (arg.equalsIgnoreCase("-fa"))
          createEnvironment(Machine.FSA, fileName);
        else if (arg.equalsIgnoreCase("-pda"))
           createEnvironment(Machine.PDA, fileName);
        else if (arg.equalsIgnoreCase("-tm") || arg.equalsIgnoreCase("-tm1"))
          createEnvironment(Machine.TM1, fileName);
        else if (arg.equalsIgnoreCase("-ttm") || arg.equalsIgnoreCase("-tm2"))
          createEnvironment(Machine.TM2, fileName);
	else if (arg.equalsIgnoreCase("-grm"))
          createEnvironment(Machine.GRA, fileName);
	else if (arg.equalsIgnoreCase("-rex"))
          createEnvironment(Machine.REX, fileName);
      }
      else 
	i++;
    }
  }	// end of method parseArgs.

  /**
   * Reads the parameters from the parameters file.
   */
  protected void readParams() {
    FileInputStream	fis;
    Properties		params = new Properties();

    try {
     fis = new FileInputStream(paramsFileName);
     params.load(fis);
     fis.close();
    } catch (Exception e) {
     System.err.println("jflap: unable to open file "+paramsFileName);
     return;
    }
    Params.load(params);
  }

  /**
   * Creates a new environment and adds it ot the list of windows
   * currently opened.
   */
  protected SourceWindow createEnvironment(int machineType, String aFileName) {
    SourceWindow sw;

    setCursor(new Cursor(Cursor.WAIT_CURSOR));
    if(machineType == Machine.GRA)
	sw = new GrammarInputWindow(aFileName, this, isApplet);
    else if(machineType == Machine.REX)
        sw = new RegExpInputWindow(this);
    else
	sw = new Environment(machineType, aFileName, this, isApplet);
    windows.addElement(sw);
    sw.setLocation((windows.indexOf(sw) + 1) * 20, 
		   (windows.indexOf(sw) + 1) * 20);
    sw.pack();
    setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    return sw;
  }

  /**
   * Shows all the Environment windows.
   */
  public void showWindows() {
    Frame f;

    for (Enumeration e=windows.elements(); e.hasMoreElements(); ) {
      f = (Frame) e.nextElement();
      f.show();
    }
  }

}  // end of class MainMenu
