/**
 *#########################################################################
 *
 * 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.
 *
 * Author: John Thompson, Greenstone Digital Library, University of Waikato
 *
 * Copyright (C) 1999 New Zealand Digital Library Project
 *
 * 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.
 *
 * 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.
 *
 * 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.cdm;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import org.greenstone.gatherer.Configuration;
import org.greenstone.gatherer.DebugStream;
import org.greenstone.gatherer.Dictionary;
import org.greenstone.gatherer.Gatherer;
import org.greenstone.gatherer.gui.GComboBox;
import org.greenstone.gatherer.gui.GLIButton;
import org.greenstone.gatherer.gui.ModalDialog;
import org.greenstone.gatherer.gui.SimpleMenuBar;
import org.greenstone.gatherer.metadata.MetadataElement;
import org.greenstone.gatherer.metadata.MetadataSetManager;
import org.greenstone.gatherer.metadata.MetadataTools;
import org.greenstone.gatherer.util.StaticStrings;
import org.greenstone.gatherer.util.Utility;

/** This class provides us with a dialog box which allows us to edit the arguments of either a Plugin or a Classifier.
 * @author John Thompson, Greenstone Digital Library, University of Waikato
 * @version 2.3
 * @see org.greenstone.gatherer.cdm.Classifier
 * @see org.greenstone.gatherer.cdm.Plugin
 */
public class ArgumentConfiguration
    extends ModalDialog
    implements ActionListener {
    /** The data whose arguments we are editing. */
    private ArgumentContainer data = null;
    /** Whether we have successfully edited the arguments associated with the ArgumentContainer or if we have failed to enter required arguments and have instead cancelled (which would cause argument additions to roll back). */
    private boolean success = false;
    /** A button to cancel this dialog. */
    private JButton cancel = null;
    /** A button to accept the changes and close the dialog. */
    private JButton ok = null;
    /** A reference to the ourselves so our inner classes can dispose us like a dialog. */
    private ArgumentConfiguration self = null;
    /** The central pane where a list of known arguments is displayed. */
    private JPanel central_pane = null;
    /** The size used for an argument label. */
    static final private Dimension LABEL_SIZE = new Dimension(225, 25);
    /** Size of a list. */
    static final private Dimension LIST_SIZE = new Dimension(380, 50);
    /** The size used for the dialog. */
    static final private Dimension SIZE = new Dimension(800, 425);

    /** Constructor.
     * @param data The plugin or classifier whose arguments we are configuring, in the form of its supported <strong>ArgumentContainer</strong> interface.
     * @see org.greenstone.gatherer.Configuration
     */
    public ArgumentConfiguration(ArgumentContainer data) {
	super(Gatherer.g_man);
	this.data = data;
	this.self = this;

	// Create
	setModal(true);
	setSize(SIZE);
	setJMenuBar(new SimpleMenuBar("designingacollection")); // can we tell whether we are doing a classifier or plugin, to make the help more specific??
	setTitle(Dictionary.get("CDM.ArgumentConfiguration.Title"));

	central_pane = new JPanel();
	JPanel content_pane = (JPanel) getContentPane();

	JLabel header = new JLabel(Dictionary.get("CDM.ArgumentConfiguration.Header", data.getName()));
	header.setHorizontalAlignment(JLabel.CENTER);
	header.setOpaque(true);
	
	JPanel button_pane = new JPanel();
	cancel = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Pure_Cancel_Tooltip"));
		
	ok = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));
	
	// Listeners
	cancel.addActionListener(this);
	ok.addActionListener(this);

	button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
	button_pane.setLayout(new GridLayout(1,2));
	button_pane.add(ok);
	button_pane.add(cancel);

	central_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
	central_pane.setLayout(new BoxLayout(central_pane, BoxLayout.Y_AXIS));

	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
	content_pane.setLayout(new BorderLayout());
	content_pane.add(header, BorderLayout.NORTH);
	JScrollPane scrollPane = new JScrollPane(central_pane);
	scrollPane.getVerticalScrollBar().setUnitIncrement(16);
	content_pane.add(scrollPane, BorderLayout.CENTER);
	content_pane.add(button_pane, BorderLayout.SOUTH);

	// Now generate a set of controls for each of the arguments.
	generateControls();

	// Display on screen.
	Dimension screen_size = Configuration.screen_size;
	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
	screen_size = null;
    }

    /** Any implementation of ActionListener must include this method so that we can be informed when an action has occured on one of the controls we are listening to.
     * @param event An <strong>ActionEvent</strong> containing pertinant information about the event that fired this call.
     * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl
     * @see org.greenstone.gatherer.cdm.ArgumentContainer
     */
    public void actionPerformed(ActionEvent event) {
	boolean cont = true;
	if (event.getSource() == ok) {
	    // Clear the current focus to ensure components such as combobox have correctly updated
	    // Loop through each of the controls in the central pane, updating the matching argument as necessary.
	    for(int i = 0; i < central_pane.getComponentCount(); i++) {
		Component component = central_pane.getComponent(i);
		if(component instanceof ArgumentControl) {
		   cont = cont && ((ArgumentControl)component).updateArgument();
		}
	    }
	    if(cont) {
		success = true;
	    }
	}
	if(cont) {
	    dispose();
	}
    }


    public void addOKButtonActionListener(ActionListener action_listener)
    {
	ok.addActionListener(action_listener);
    }


    /** Destructor. */
    public void destroy() {
	cancel = null;
	central_pane = null;
	//custom_pane = null;
	//custom = null;
	data = null;
	ok = null;
	self = null;
    }

    /** Method which actually forces the dialog to be shown on screen.
     * @return <i>true</i> if the user completed configuration and pressed ok, <i>false</i> otherwise.
     */
    public boolean display() {
	setVisible(true);
	return success;
    }

    private void addHeader(String name, Color color) {
	JPanel header = new JPanel();
	header.setBackground(color);
	JPanel inner_pane = new JPanel();
	inner_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createRaisedBevelBorder()));
	inner_pane.setBackground(color);
	JLabel header_label = new JLabel("<html><strong>" + name + "</strong></html>");
	header_label.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
	header_label.setHorizontalAlignment(JLabel.CENTER);
	header_label.setOpaque(true);

	// Layout
	inner_pane.setLayout(new BorderLayout());
	inner_pane.add(header_label, BorderLayout.CENTER);

	header.setLayout(new BorderLayout());
	header.add(inner_pane, BorderLayout.CENTER);
	central_pane.add(header);
    }

    /** Method to iterate through the arguments associated with whatever argument container we are building an argument control view for, creating the appropriate controls for each.
     * @see org.greenstone.gatherer.cdm.Argument
     * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl
     */
    private void generateControls() {
	// Alternating colours to show inheritance
	Color colour_one = Configuration.getColor("coloring.collection_heading_background", false);
	Color colour_two = Configuration.getColor("coloring.collection_tree_background", false);
	boolean coloured = false;
	ArrayList arguments = data.getArguments();
	int total_height = 250;
	// not currently used
	//int current_mode = Configuration.getMode();

	String previous_owner = "";
	if(arguments.size() > 0) {
	    previous_owner = ((Argument) arguments.get(0)).getOwner();
	    addHeader(previous_owner, colour_two);
	}

	for(int i = 0; i < arguments.size(); i++) {
	    Argument argument = (Argument) arguments.get(i);
	    String owner = argument.getOwner();
	    if(previous_owner != argument.getOwner()) {
	    ///ystem.err.println("previous owner is different from current owner");
		coloured = !coloured;
		previous_owner = argument.getOwner();
		addHeader(previous_owner, (coloured ? colour_one : colour_two));
	    }
	    if(!argument.isHiddenGLI()) {
		ArgumentControl argument_control = new ArgumentControl(argument, false, null);
		total_height = total_height - argument_control.getPreferredSize().height;
		// Create
		if(coloured) {
		    argument_control.setBackground(colour_one);
		}
		else {
		    argument_control.setBackground(colour_two);
		}

		central_pane.add(argument_control);
	    }
	}
	if(total_height > 0) {
	    JPanel filler = new JPanel();
	    filler.setPreferredSize(new Dimension(100, total_height));
	    filler.setSize(new Dimension(100, total_height));
	    central_pane.add(filler);
	}
    }

}
