// file: SearchMenu.java
//

// import java libraries
//
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

/**
 * Search menu functionalities
 * An extension of JPanel and implements ActionListener
 */
public class SearchMenu extends JPanel implements ActionListener{

    // declare global variables
    // 
    JPanel menu = null;
    
    // font to set everything to
    //
    Font newFont = null;

    JMenu[] menuGenerationQueue;

    JMenuBar menu_bar;

    public final int PLAIN = 0;
    public final int CHECK = 1;

    public final int NONE = 0;
    public final int VARMINT_PANEL = 1;
    public final int SEARCH_MENU = 2;

    Vector names = null;
    Vector enums = null;
    VarmintDB database = null;

    VarmintPanel varmintPanel = null;
    
    // ---------------------------------------------------
    //
    // declare class constructors
    //
    // ---------------------------------------------------
   
    /**
     * default class constructor
     * @param varmintPanel_ VarmintPanel used for initializing
     */
    public SearchMenu(VarmintPanel varmintPanel_) {
	
	varmintPanel = varmintPanel_;
	database = varmintPanel.database;

	newFont = varmintPanel.newFont;

	Config config = new Config();
	Vector 	configVector = database.getConfig();
	names = config.create_names();
	enums = config.create_enums(configVector);
		
	menuGenerationQueue = new JMenu[15];
	menu_maker(this, varmintPanel);

    }
    
    
    /**
     * this function has been modified to create completely the menu for
     * this program 
     * @param menu_panel panel to hold the menubar
     * @param target tells which panel is to have the menu
     */
    public void menu_maker(JPanel menu_panel, JPanel target) {

	// create a border around the menu panel
        //
        menu_panel.setBorder(BorderFactory.createEtchedBorder());

	// make this menu panel use a gridbag layout and set up the 
	// contraints so that they menu will display properly
	//
	menu_panel.setLayout(new GridBagLayout());
	GridBagConstraints gbc = new GridBagConstraints();
	gbc.gridx = 0;
	gbc.gridy = 0;
	gbc.gridwidth = GridBagConstraints.REMAINDER;
	gbc.gridheight = GridBagConstraints.REMAINDER;
	gbc.weightx = 1;
	gbc.weighty = 1;
	gbc.fill = GridBagConstraints.HORIZONTAL;

	menu_bar = new JMenuBar();
	menu_panel.add(menu_bar, gbc);


	// create the file menu
	//
	menu_bar.add(makeMenu("File", new Object[] {
	    "New" ,"Load", "Save" , null, 
	    "Close", "Exit"}, target, PLAIN, VARMINT_PANEL));

	
	((JMenu)menu_bar.getComponent(0)).
	    getMenuComponent(4).setEnabled(false);
	((JMenu)menu_bar.getComponent(0)).
	    getMenuComponent(1).setEnabled(false);


	// create an edit menu
	//
	menu_bar.add(makeMenu("Edit", new Object[] {
	    "Cut", "Paste",
	    "Copy", null, "Configuration", "Unlock All", null,
	    "Preferences" }, target, PLAIN, VARMINT_PANEL));

	// disable the edit menu for now
	//
	for (int i = 0 ; i < 8; i++) {
	    ((JMenu)menu_bar.getComponent(1)).
		getMenuComponent(i).setEnabled(false);
	}
	
	if (database.isAdmin(varmintPanel.user)) {
	    ((JMenu)menu_bar.getComponent(1)).
		getMenuComponent(4).setEnabled(true);
	    ((JMenu)menu_bar.getComponent(1)).
		getMenuComponent(5).setEnabled(true);
	}

	
	// create a view menu
	//
	menu_bar.add(makeMenu("View", new Object[] {
	    "SQL"}, target, CHECK, VARMINT_PANEL));
	((JCheckBoxMenuItem)((JMenu)menu_bar.getComponent(2)).
	 getMenuComponent(0)).setState(true);

	Vector loadedSubMenus = createLoadedSubMenu(target);

	// create an action menu
	//
	JMenu statMenu = createStatSubMenu(target);
	menu_bar.add(makeMenu("Action", new Object[] {
	    "New Bug", "Find Bug",
	    null, "Execute",null, statMenu, null, (JMenu)loadedSubMenus.get(0),
	    (JMenu)loadedSubMenus.get(1),
	    (JMenu)loadedSubMenus.get(2)},
			      target, PLAIN, VARMINT_PANEL));
	
	// create a statistics menu
	//
	/*	menu_bar.add(makeMenu("Statistics", new Object[] {
	    "By Owner", "By Status", "By Database", "By Class", 
	    "By Priority", "By Severity", "By Due Date",
	    "By Resolution", "By Inspected By", "By Environment",
	    "By Test Case", "By Component", "By OpenedBy", "By ResolvedBy",
	    "By ClosedBy"}, 
	    target, PLAIN, VARMINT_PANEL));*/

	// create a query menu
	//
	createQuerySubMenu(target);
	
	menu_bar.add(makeMenu("Query", menuGenerationQueue, target, 
			      PLAIN, VARMINT_PANEL));

	
	// add the space between the regular menu items and the help
	//
	menu_bar.add(Box.createHorizontalGlue());

	// create the help menu
	//
	menu_bar.add(makeMenu("Help", 
			      new Object[] {"Overview",
					    "Tutorial", null, "Release Notes",
					    null, "About Varmint", 
					    "About Authors"}, target, PLAIN,
					    VARMINT_PANEL));
    
	// disable the help menu for now
	//
	for (int i = 0 ; i < 7; i++) {
	    ((JMenu)menu_bar.getComponent(6)).
		getMenuComponent(i).setEnabled(false);
	}
    }
    
    
   
    /**
     * allow the user to take a returned menu and do with it
     * as they see fit
     * @param parent   name of or menu that will contain the items
     * @param items    names of the menu items that are to be added
     * @param target   tells where the event handlers are
     * @param mode     mode used
     * @param actions  actions used
     *
     * @return individual dropdown menus
     */
    private JMenu makeMenu(Object parent, Object[] items, 
			   Object target, int mode, int actions) {
	JMenu m = null;
	
	
	//  at this point, the parent Object is examined.  if it is a string,
	//  a new menu item is created, but if it is a menu, then the menu
	//  is renamed to m
	//
	if (parent instanceof JMenu) {
	    m = (JMenu)parent;
	    m.setFont(newFont);
	}
	else if (parent instanceof String) {
	    m = new JMenu ( (String) parent);
	    m.setFont(newFont);
	}
	else 
	    return null;
	
	// here the individual menu items are added to the menu and an 
	// action listener is added with the name of the item being
	// the way to access it
	//
	for (int i = 0; i < items.length; i++) {
	    if (items[i] instanceof String) {
		
		JMenuItem mi = new JMenuItem("");

		if (mode == PLAIN) {
		    mi = new JMenuItem((String)items[i]);
		}
		else if (mode == CHECK) {
		    mi = new 
			JCheckBoxMenuItem((String)items[i]);
		}
		
		mi.setFont(newFont);

		if (actions == SEARCH_MENU) {
		    mi.addActionListener(this);
		}
		else if (target instanceof ActionListener)
		    mi.addActionListener((ActionListener) target);
		
		if (actions == NONE) {
		    mi.setActionCommand("Generate Query");
		}
		
		m.add(mi);
	    }
	    else if (items[i] instanceof JMenuItem) {
		JMenuItem mi = new JMenuItem("");
		
		if (mode == PLAIN) {
		    mi = (JMenuItem)items[i];
		}
		else if (mode == CHECK) {
		    mi = (JCheckBoxMenuItem)items[i];
		}

		mi.setFont(newFont);

		if (actions == SEARCH_MENU) {
		    mi.addActionListener(this);
		}
		else if (target instanceof ActionListener)
		    mi.addActionListener((ActionListener)target);
		
		if (actions == NONE) {
		    mi.setActionCommand("Generate Query");
		}
		
		m.add(mi);
		
	    }
	    else if (items[i] == null)
		m.addSeparator();
	}
	return m;
    }


    private void createQuerySubMenu(JPanel target) {

	for (int i=0; i < 12; i++) {
	
	    Vector currentVector = ((Vector)enums.get(i));
	    currentVector.remove(0);

	    if (names.get(i).equals("Component")) {
		menuGenerationQueue[i] = 
		    makeMenu((String)names.get(i), 
			     database.getAllComponents().toArray(),
			     target, CHECK, NONE);
		
	    }
	    else {
		menuGenerationQueue[i] = 
		    makeMenu((String)names.get(i), 
			     currentVector.toArray(), target, CHECK, NONE);
		
	    }
	}

	menuGenerationQueue[12] =
	    makeMenu("Status", new Object[] {"Open", "Resolved", "Closed"},
		     target, CHECK, SEARCH_MENU);

	names.insertElementAt("All", 0);
	names.add("Status");

	menuGenerationQueue[14] = makeMenu("Default", names.toArray(),
					   target, PLAIN, SEARCH_MENU);
    }


    /**
     * uses the data in the Query menus to generate a new query
     * @return String of new Query
     */
    public String generateQuery() {
	
	// holds the query string that will be run
	//
	String query = new String("select bug_list.* from bug_list \n");
	
	// hold the query generate by any one field so that parentheses can be
	// added as neccesary to OR's fields
	//
	String subquery = new String("");
	
	// allows the where or and clause to float along and not get added 
	// until the subquery is also ready
	//
	String prefix = new String("");

	// flag for allowing the system to know if there is already a query
	// added and then will AND them together
	//
	boolean added1 = false;
	

	// flag showing whether two terms have been OR'd
	//
	boolean flag2 = false;

	// the query menu
	//
	JMenu menu = (JMenu)(menu_bar.getComponent(4));

	
	// loop through the 12 submenus
	//
	for (int i=0; i < 13; i++) { 
	  
	    // the submenu for each component
	    //
	    JMenu submenu = (JMenu)(menu.getMenuComponent(i));
	    
	    // if this is true, a first item from a submenu has been added and
	    // therefore all later queries should be OR'd
	    //
	    boolean flag1 = false;
	  

	    // step through each item in the submenu
	    //
	    for (int j = 0; j < submenu.getItemCount(); j++) {
		
		JCheckBoxMenuItem item =(JCheckBoxMenuItem)
		    (submenu.getMenuComponent(j));
		
		// get the label on the submenu
		//
		String label = submenu.getText();

		
		// convert the Label Database into DBase
		//
		if (label.equals("Database"))
		    label = "DBase";
		
		// if the item is selected, process it
		//
		if (item.getState()) {

		  
		    // if nothing at all has been added to the query
		    // place a where at the beginning and add the selection
		    // to the subquery
		    //
		    if  ((!added1) && (!flag1)) {
			prefix += "where "; 
			added1 = true;
			flag1 = true;
			subquery += "(bug_list." + label + " = '" 
			    + item.getText() + "')";
		    }
		    // if something has been added, but not from this 
		    // submenu
		    //
		    else if ((added1) && (!flag1)){
			prefix += " and ";
			flag1 = true;
			subquery += "(bug_list." + label + " = '" 
			    + item.getText() + "')";
		    }
		    // if something has been added from this submenu before
		    //
		    else if ((flag1) && (added1)){
			subquery += "or (bug_list." + label + " = '" 
			    + item.getText() + "')";
			flag2 = true;
		    }
		    
		}
	    }
	    // add the prefix statement to the query
	    //
	    query += prefix;
	    
	    // if statements have been OR'd, add parentheses
	    //
	    if (flag2) {
		subquery = "(" + subquery + ")";
	    }

	    // separate the queries into multiple lines
	    //
	    if (!subquery.equals("")) {
		subquery  = subquery + "\n     ";
	    }

	    // add the subquery to the query
	    //
	    query += subquery;

	    // clear out all of the values specific to a single submenu and
	    // go grab the rest of them
	    //
	    subquery = "";
	    prefix = "";
	    flag2 = false;
	    
	    
	}
	return query;
    }

    /**
     * Clears a sub menu
     * @param select int parameter of which sub menu to clear
     */
    public void clearSubMenu(int select) {
	
	// the query menu
	//
	JMenu menu = (JMenu)(menu_bar.getComponent(4));
	
	// the submenu for each component
	//
	JMenu submenu = (JMenu)(menu.getMenuComponent(select));
	

	// step through each item in the submenu
	//
	for (int j = 0; j < submenu.getItemCount(); j++) {
	    
	    JCheckBoxMenuItem item =(JCheckBoxMenuItem)
		(submenu.getMenuComponent(j));

	    // turn the check box off
	    //
	    item.setState(false);
	}
    }


    /**
     * listens for actions taking place on the components
     *
     * @param e ActionEvent that was fired
     */
    public void actionPerformed(ActionEvent e) {

	String command = e.getActionCommand();

	if (command.equals("All")) {
	    
	    for(int i=0; i < 13; i++) {
		clearSubMenu(i);

		String query = generateQuery();
		varmintPanel.bugSearch.bugQuery.queryEntry.setText(query);
	    }
	}

	else if (command.equals("DBase")) {

	    clearSubMenu(1);
	    String query = generateQuery();
	    varmintPanel.bugSearch.bugQuery.queryEntry.setText(query);
	}
	
	else {
	    int select = names.indexOf(command);
	    if (select >= 0) {
		clearSubMenu(select-1);
	    }
	    String query = generateQuery();
	    varmintPanel.bugSearch.bugQuery.queryEntry.setText(query);
	}
    }
    
    /**
     * creates a stat submenu
     * @param target JPanel to add submenu, used for listening target
     * @return JMenu created as subpanel
     */
    public JMenu createStatSubMenu(JPanel target) {
	
	String queries[] = {"By Owner", "By Status", "By Database", 
			    "By Class", "By Priority", "By Severity", 
			    "By Due Date", "By Resolution", "By Inspected By",
			    "By Environment", "By Test Case", "By Component", 
			    "By OpenedBy", "By ResolvedBy", "By ClosedBy"};
	

	JMenu statMenu = new JMenu("Statistics");
	statMenu.setFont(newFont);
	
	for (int i = 0; i < 15; i++) {
	    JMenuItem t = new JMenuItem(queries[i]);
	    t.setFont(newFont);
	    
	    t.addActionListener((VarmintPanel)target);
	    
	    statMenu.add(t);
	}
	
	return statMenu;
    }
	
    /**
     * creates a loaded submenu
     * @param target JPanel to a create to, used for listening target
     * @return Vector of created menues
     */
    public Vector createLoadedSubMenu(JPanel target) {
	
	Vector queries = varmintPanel.database.loadQueries(varmintPanel.user);

	JMenu varmintMenu = new JMenu("Standard");
	varmintMenu.setFont(newFont);
	JMenu privateMenu = new JMenu("Personal");
	privateMenu.setFont(newFont);
	JMenu publicMenu = new JMenu("Other");
	publicMenu.setFont(newFont);
	Vector returnVector = new Vector(3);

	returnVector.add(varmintMenu);
	returnVector.add(privateMenu);
	returnVector.add(publicMenu);

	Vector names = (Vector)enums.get(0);
	for (int i = 0; i < names.size(); i++) {
	    JMenu t = new JMenu((String)names.get(i));
	    t.setFont(newFont);
	    publicMenu.add(t);
	}

	Vector usersGroups = getUsersGroups();

	for(int i = 0; i < queries.size(); i++) {
	    
	    final Vector individual = (Vector)queries.get(i);
	    
	    if (individual.get(0).equals("VARMINT")) {
		
		JMenuItem item = new JMenuItem((String)individual.get(1));
		item.setFont(newFont);

		item.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
			    
			    int index = 0;
			    String query_title = (String)individual.get(1);
			    String query = (String)individual.get(2);
			    
			    while (index != -1) {

				index = query.indexOf("$VARMINT_USER$");

				if (index != -1) {
				    query = query.substring(0,index) + 
					varmintPanel.user + 
					query.substring(index + 14, 
							query.length());
				}

			    }
			    
			    varmintPanel.bugSearch.bugQuery.queryEntry.
				setText(query);
			    
			    BugQuery.setQueryString(query_title);
			    BugQuery.setQueryModify(false);
			    varmintPanel.actionExecuteQuery();
			}
		    });
		varmintMenu.add(item);
		
	    }
	    
	    else {
		
		// this is the public "Other" menu's
		//
		if (usersGroups.indexOf((String)individual.get(3)) >= 0) {
		    
		    JMenuItem item = new JMenuItem((String)individual.get(1));
		    item.setFont(newFont);
		    
		    item.addActionListener(new ActionListener() {
			    public void actionPerformed(ActionEvent e) {
				

				// replace the special string
				// $VARMINT_USER$ with the username
				//
				int index = 0;
				String query_title = (String)individual.get(1);
				String query = (String)individual.get(2);
				
				while (index != -1) {
				    
				    index = query.indexOf("$VARMINT_USER$");
				    
				    if (index != -1) {
					query = query.substring(0,index) + 
					    varmintPanel.user + 
					    query.substring(index + 14, 
							    query.length());
				    }
				    
				}
				
				varmintPanel.bugSearch.bugQuery.queryEntry.
				    setText(query);
				
				BugQuery.setQueryString(query_title);
				BugQuery.setQueryModify(false);

				varmintPanel.actionExecuteQuery();
			    }
			});
		    
		    int position = ((Vector)enums.get(0)).
			indexOf(individual.get(0));
		    
		    /*
		    if (position < 0) {
			RuntimeException e = new RuntimeException("query exists for nonexistant user "+individual.get(0));
			throw(e);
		    }
		    */
		    if (position >= 0) {
			((JMenu)publicMenu.getMenuComponent(position)).add(item);
		    }
		}
	    }

	    if (individual.get(0).equals(varmintPanel.user)) {
		
		JMenuItem item = new JMenuItem((String)individual.get(1));
		item.setFont(newFont);
		
		item.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
			    
			    int index = 0;
			    String query_title = (String)individual.get(1);
			    String query = (String)individual.get(2);
			    
			    while (index != -1) {

				index = query.indexOf("$VARMINT_USER$");

				if (index != -1) {
				    query = query.substring(0,index) + 
					varmintPanel.user + 
					query.substring(index + 14, 
							query.length());
				}

			    }
			    
			    varmintPanel.bugSearch.bugQuery.queryEntry.
				setText(query);

			    BugQuery.setQueryString(query_title);
			    BugQuery.setQueryModify(false);
			    
			    varmintPanel.actionExecuteQuery();
			}
		    });
		privateMenu.add(item);
	    }


	}
	return returnVector;
    }

    /**
     * get all of the groups for sharing from the database and put
     * them into a Vector
     */
    Vector getUsersGroups () {
	// get all of the groups for sharing from the database and put
	// them into a Vector
	//
	Vector  shareGroups = varmintPanel.database.getGroups();

	Vector groups = new Vector(5,5);
	groups.add("public");

	
	
	for (int i =0 ; i < shareGroups.size(); i++) {

	    // create the vector to hold each of the enum values
	    //
	    Vector groupUsers = (Vector)shareGroups.get(i);
	    	    		
	    String members = (String)groupUsers.get(1);
	    // tokenize the string containing the values with comma as the
	    // delimiter
	    //
	    StringTokenizer tokenizer = new StringTokenizer(members, ",");
	    
	    // run through and add each token to the shareGroups vector
	    //
	    while (tokenizer.hasMoreTokens()) {
		
		String line = (String)tokenizer.nextToken();
		line = line.trim();
		
		if (line.equals(varmintPanel.user)) {
		    
		    String group = (String)groupUsers.get(0); 
		    
		    groups.add(group);
		    if (group.equals("admin")) {
			groups.add("varmint");
		    }
		}
	    }
	}
	
	return groups;
    }


    void updateMenus() {

	Vector subMenu = createLoadedSubMenu(varmintPanel);
	
	JMenu actionMenu = ((JMenu)menu_bar.getComponent(3));
	actionMenu.setFont(newFont);
	int count = actionMenu.getItemCount();
	for (int i = 0; i < 3; i++) {
	    actionMenu.remove(count-i-1);
	}
	actionMenu.insert((JMenu)subMenu.get(0), count-3);
	actionMenu.insert((JMenu)subMenu.get(1), count-2);
	actionMenu.insert((JMenu)subMenu.get(2), count-1);
    }
}














