/**
 *#########################################################################
 *
 * A component of the Gatherer application, part of the Greenstone digital
 * library suite from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * <BR><BR>
 *
 * Author: John Thompson, Greenstone Digital Library, University of Waikato
 *
 * <BR><BR>
 *
 * Copyright (C) 1999 New Zealand Digital Library Project
 *
 * <BR><BR>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * <BR><BR>
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * <BR><BR>
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *########################################################################
 */
package org.greenstone.gatherer.gui;

import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import org.greenstone.gatherer.Configuration;
import org.greenstone.gatherer.DebugStream;
import org.greenstone.gatherer.Dictionary;
import org.greenstone.gatherer.Gatherer;
import org.greenstone.gatherer.cdm.CollectionDesignManager;
import org.greenstone.gatherer.cdm.Control;

/** This class is responsible for generating the necessary GUI components. It does this by calling the getEditControls() method of the appropriate class (i.e. IndexManager for index related edits). It also is in charge of correctly adding (and removing) listeners, using phrases from the <strong>Dictionary</strong> rather than the text keys inserted in the component classes, and several other aspects of the design page, including the config file section tree.

/** This is a base class for Design and Format panes, which are very similar except that they have different components.  */
public abstract class BaseConfigPane 
    extends JPanel {

    /* This should list the contents of the contents */
    protected String contents[]; 
    
    /** The preferred size of the contents tree. */
    static final private Dimension TREE_SIZE = new Dimension(200, 500);

    /** The panel apon which is rendered the currently selected section screen. */
    protected Control view = null;
    protected String view_type = null;
    /** The collection manager is responsible for parsing in, and allowing the editing of, a single collections configuration file. */
    protected CollectionDesignManager cdm = null;
    /** A tree to serve as a 'table of contents' for this design tool. We decided on a tree rather than a list, as it allows us to break sections into subsections if they become to complicated. */
    protected DesignTree tree;
    protected JPanel tree_pane;
    /** The constructor. */
    public BaseConfigPane() {
	super();
	DebugStream.println("BaseConfigPane: Main GUI components created.");
	// Creation
        this.setComponentOrientation(Dictionary.getOrientation());
	tree_pane = new JPanel();
        tree_pane.setComponentOrientation(Dictionary.getOrientation());
        
	tree = new DesignTree();
	tree.setComponentOrientation(Dictionary.getOrientation());
	// Connect
	tree.addTreeSelectionListener(new TreeListener());

	// Layout
	tree_pane.setLayout(new BorderLayout());
	tree_pane.setPreferredSize(TREE_SIZE);
        JScrollPane scrol_tmp;
        scrol_tmp = new JScrollPane(tree);
        scrol_tmp.setComponentOrientation(Dictionary.getOrientation());
	tree_pane.add(scrol_tmp, BorderLayout.CENTER);
	setLayout(new BorderLayout());
	setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
	
	add(tree_pane, BorderLayout.LINE_START);


    }

    abstract protected Control getSubControls(String type);
    
    /** Called to cause the components to lay themselves out and be displayed.
     */
    public void display() {
    }


    public void gainFocus()
    {
	if (cdm == null && Gatherer.c_man.ready()) {
	    // Retrieve the new config manager.
	    cdm = Gatherer.c_man.getCollection().cdm;
	}
	if (view != null) {
	    view.gainFocus();
	}
    }


    public void loseFocus()
    {
	if (view != null) {
	    view.loseFocus();
	}
	if (cdm != null) {
	    Gatherer.c_man.saveCollection();
	}
    }


    public void destroy() {
	tree = null;
	view = null;
    }

    /** Called whenever the detail mode changes to ensure the filters are at an appropriate level (ie only editable by those that understand regular expression matching)
     * @param mode the mode level as an int
     */
    public void modeChanged(int mode) {
	if (cdm != null) {
	    cdm.modeChanged(mode);
	}
    }

    /** This method is called whenever the state of the current collection changes.
     */
    public void refresh(int refresh_reason, boolean ready)
    {
	if (ready) {
	    // Retrieve the new config manager.
	    cdm = Gatherer.c_man.getCollection().cdm;
	    tree.resetModel(Configuration.getMode()); // does this set view??
	}
    }


    /** Force the display to show a certain pane of controls.
     * @param type a String giving the name of the information manager or view we wish to display
     */
    public void setSelectedView(String type) {
	tree.setSelectedView(type);
    }

    /** This tree provides a 'table of contents' for the various components of the design process (collection configuration in more technical terms). */
    private class DesignTree
	extends JTree {
	private DesignNode root = null;
	/** Constructor. Automatically generates all of the nodes, in the order of contents. */
	public DesignTree() {
	    super();
	}

	/** Reset the model used by the design page contents tree. This is necessary to hide the partitions entry when in lower detail modes
	 * @param mode the current detail mode as an int
	 */
	public void resetModel(int mode) {
	    root = new DesignNode("CDM.GUI.Root");
	    // Now add the design categories.
	    for(int i = 0; i < contents.length; i++) {
		root.add(new DesignNode(contents[i]));
	    }
	    this.setModel(new DefaultTreeModel(root));
	    expandRow(0);
	    setRootVisible(false);
	    setSelectionRow(0);
	    updateUI();
	}
	/** Set the current view to the one specified.
	 * @param type the name of the desired view as a String
	 */
	public void setSelectedView(String type) {
	    type = Dictionary.get(type);
	    for(int i = 0; i < root.getChildCount(); i++) {
		DesignNode child = (DesignNode) root.getChildAt(i);
		if(child.toString().equals(type)) {
		    TreePath path = new TreePath(child.getPath());
		    setSelectionPath(path);
		}
	    }
	}
    }
    /** A tree node that retains a reference to one of the possible design sub-views relating to the different sub-managers. */
    private class DesignNode
	extends DefaultMutableTreeNode {
	/** Constructor.
	 * @param object The <strong>Object</strong> assigned to this node.
	 */
	public DesignNode(String object) {
	    super(object);
	}
	/** Retrieve a textual representation of the object.
	 * @return a String
	 */
	public String toString() {
	    // return Dictionary.get("CDM.GUI." + (String)getUserObject());
	    return Dictionary.get((String) getUserObject());
	}
    }
    /** Listens for selection changes in the 'contents' tree, and switches to the appropriate view. */
    private class TreeListener
	implements TreeSelectionListener {
	/** Called whenever the selection changes, we must update the view so it matches the node selected.
	 * @param event A <strong>TreeSelectionEvent</strong> containing more information about the tree selection.
	 */
	public void valueChanged(TreeSelectionEvent event) {
	    if(!tree.isSelectionEmpty()) {
		TreePath path = tree.getSelectionPath();
		DesignNode node = (DesignNode)path.getLastPathComponent();
		String type = (String)node.getUserObject();
		// Wait begins
		Gatherer.g_man.wait(true);
		// Save information in current view
		if (view != null) { // can we get rid of this??
		    view.loseFocus();
		    remove((JPanel)view);
		}
		view_type = type;
		// Change panes.
		view = getSubControls(type);
		if (view != null) {
		    add((JPanel)view, BorderLayout.CENTER);
		    // Update information on visible pane
		    view.gainFocus();
		}
		repaint();
		// Wait ends
		Gatherer.g_man.wait(false);
	    }
	}
    }
}
