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

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
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.ClassifierManager;
import org.greenstone.gatherer.cdm.LanguageManager;
import org.greenstone.gatherer.cdm.PluginManager;
import org.greenstone.gatherer.collection.Collection;
import org.greenstone.gatherer.gui.tree.DragTree;
import org.greenstone.gatherer.util.ArrayTools; // just for debug
import org.greenstone.gatherer.util.CheckList;
import org.greenstone.gatherer.util.CheckListEntry;
import org.greenstone.gatherer.util.StaticStrings;
import org.greenstone.gatherer.util.XMLTools;
import org.w3c.dom.*;

public class Preferences
    extends ModalDialog
{
    static final public String CONNECTION_PREFS = "connection";
    static final public String GENERAL_PREFS = "general";

    static final private Dimension LABEL_SIZE = new Dimension(280, 25);
    static final private Dimension ROW_SIZE = new Dimension(640, 25);
    static final private Dimension SIZE = new Dimension(640, 345);
    static final private String TRUE = "true";

    private CheckList warning_preferences_check_list;
    private EmailField email_field;
    private JButton apply_button;
    private JButton cancel_button;
    private JButton ok_button;
    private JCheckBox show_file_size_checkbox;
    private JCheckBox use_proxy_checkbox;
    private JCheckBox view_extracted_metadata_checkbox;
    private JCheckBox workflow_download;
    private JCheckBox workflow_gather;
    private JCheckBox workflow_enrich;
    private JCheckBox workflow_design;
    private JCheckBox workflow_create;
    private JCheckBox workflow_format;
    private JComboBox language_combobox;
    private JComboBox servlet_combobox; // GS3
    private JComboBox site_combobox; // GS3
    private JRadioButton assistant_mode_radio_button;
    private JRadioButton expert_mode_radio_button;
    private JRadioButton librarian_mode_radio_button;
    private JRadioButton systems_mode_radio_button;
    private JSpinner proxy_port_field;
    private JTabbedPane tab_pane;
    private JTextArea mode_description_textarea;
    private JTextField font_field;
    private JTextField gliserver_url_field;
    private JTextField library_path_field;
    private JTextField program_field;
    private JTextField proxy_host_field;
    private Preferences self;

    private String current_site_selection;

    public Preferences() {
	this(GENERAL_PREFS);
    }

    public Preferences(String initial_view) {
	// Initialize
	super(Gatherer.g_man, true);
	this.self = this;
	setSize(SIZE);
	setTitle(Dictionary.get("Preferences"));
	setJMenuBar(new SimpleMenuBar("preferences"));

	// Creation
	JPanel content_pane = (JPanel) getContentPane();
	tab_pane = new JTabbedPane();
	JPanel general_preferences = createGeneralPreferences();
	tab_pane.addTab(Dictionary.get("Preferences.General"), null, general_preferences, Dictionary.get("Preferences.General_Tooltip")); 
	tab_pane.addTab(Dictionary.get("Preferences.Mode"), null, createModePreferences(), Dictionary.get("Preferences.Mode_Tooltip"));
	//	tab_pane.addTab(Dictionary.get("Preferences.Workflow"), null, createWorkflowPreferences(), Dictionary.get("Preferences.Workflow_Tooltip")); 
	JPanel connection_preferences = createConnectionPreferences();
	tab_pane.addTab(Dictionary.get("Preferences.Connection"), null, connection_preferences, Dictionary.get("Preferences.Connection_Tooltip")); 
	tab_pane.addTab(Dictionary.get("Preferences.Warnings"), null, createWarningPreferences(), Dictionary.get("Preferences.Warnings_Tooltip")); 
	
	JPanel button_pane = new JPanel();
	ok_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));
	
	apply_button = new GLIButton(Dictionary.get("General.Apply"), Dictionary.get("General.Apply_Tooltip"));
	
	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel_Tooltip"));
	
	// Connection
	ok_button.addActionListener(new OKButtonListener(true));
	apply_button.addActionListener(new OKButtonListener(false));
	cancel_button.addActionListener(new CancelButtonListener());

	// Layout
	button_pane.setBorder(BorderFactory.createEmptyBorder(5,2,2,2));
	button_pane.setLayout(new GridLayout(1,3,0,5));
	button_pane.add(ok_button);
	button_pane.add(apply_button);
	button_pane.add(cancel_button);

	content_pane.setLayout(new BorderLayout());
	content_pane.add(tab_pane, BorderLayout.CENTER);
	content_pane.add(button_pane, BorderLayout.SOUTH);

	Dimension frame_size = Gatherer.g_man.getSize();
	Point frame_location = Gatherer.g_man.getLocation();
	setLocation(((frame_size.width - SIZE.width) / 2), ((frame_size.height - SIZE.height)));

	// Bring the desired pane to the fore
	if (initial_view.equals(CONNECTION_PREFS)) {
	    tab_pane.setSelectedComponent(connection_preferences);
	}
	else {
	    tab_pane.setSelectedComponent(general_preferences);
	}
	
	// Clean up
	general_preferences = null;
	connection_preferences = null;
	frame_location = null;
	frame_size = null;
	cancel_button = null;
	ok_button = null;
	button_pane = null;
	tab_pane = null;
	content_pane = null;

	setVisible(true);
    }

    private JPanel createConnectionPreferences() {
	JPanel program_pane = new JPanel();
	program_pane.setPreferredSize(ROW_SIZE);
	JLabel program_label = new JLabel(Dictionary.get("Preferences.Connection.ProgramCommand"));
	program_label.setPreferredSize(LABEL_SIZE);
	
	program_field = new JTextField(Configuration.getPreviewCommand());
	program_field.setCaretPosition(0);
	program_field.setToolTipText(Dictionary.get("Preferences.Connection.ProgramCommand_Tooltip"));
	
	JPanel library_path_pane = new JPanel();
	library_path_pane.setPreferredSize(ROW_SIZE);
	JLabel library_path_label = new JLabel();
	library_path_label.setPreferredSize(LABEL_SIZE);
	String library_url_string = "";
	if (Configuration.library_url != null) {
	    library_url_string = Configuration.library_url.toString();
	}
	library_path_field = new JTextField(library_url_string);
	library_path_field.setCaretPosition(0);
	if (Gatherer.GS3) {
	    library_path_label.setText(Dictionary.get("Preferences.Connection.Library_Path_GS3"));
	    library_path_field.setToolTipText(Dictionary.get("Preferences.Connection.Library_Path_Tooltip_GS3"));
	} else {
	    library_path_label.setText(Dictionary.get("Preferences.Connection.Library_Path"));
	    library_path_field.setToolTipText(Dictionary.get("Preferences.Connection.Library_Path_Tooltip"));
	}
	    
	// Disable this field when using the applet, as it is automatically determined
	library_path_label.setEnabled(!Gatherer.isApplet);
	library_path_field.setEnabled(!Gatherer.isApplet);

	JPanel gliserver_url_pane = null;
	JLabel gliserver_url_label = null;
	if (Gatherer.isGsdlRemote) {
	    gliserver_url_pane = new JPanel();
	    gliserver_url_pane.setPreferredSize(ROW_SIZE);
	    gliserver_url_label = new JLabel(Dictionary.get("Preferences.Connection.GLIServer_URL"));
	    gliserver_url_label.setPreferredSize(LABEL_SIZE);
	    String gliserver_url_string = "";
	    if (Configuration.gliserver_url != null) {
		gliserver_url_string = Configuration.gliserver_url.toString();
	    }
	    gliserver_url_field = new JTextField(gliserver_url_string);
	    gliserver_url_field.setCaretPosition(0);
	    gliserver_url_field.setToolTipText(Dictionary.get("Preferences.Connection.GLIServer_URL_Tooltip"));
	    
	    // Disable this field when using the applet, as it is automatically determined
	    gliserver_url_label.setEnabled(!Gatherer.isApplet);
	    gliserver_url_field.setEnabled(!Gatherer.isApplet);
	}

	JPanel site_pane = null;
	JLabel site_label = null;
	JPanel servlet_pane = null;
	JLabel servlet_label = null;
	if (Gatherer.GS3) {
	    site_pane = new JPanel();
	    site_pane.setPreferredSize(ROW_SIZE);
	    site_label = new JLabel(Dictionary.get("Preferences.Connection.Site"));
	    site_label.setPreferredSize(LABEL_SIZE);
	    // what should we do if Gatherer.servlet_config.getSites() is null?
	    site_combobox = new JComboBox(Gatherer.servlet_config.getSites().toArray());
	    site_combobox.setOpaque(false);
	    site_combobox.setToolTipText(Dictionary.get("Preferences.Connection.Site_Tooltip"));
	    
	    servlet_pane = new JPanel();
	    servlet_pane.setPreferredSize(ROW_SIZE);
	    servlet_label = new JLabel(Dictionary.get("Preferences.Connection.Servlet"));
	    servlet_label.setPreferredSize(LABEL_SIZE);
	    servlet_combobox = new JComboBox();
	    servlet_combobox.setOpaque(false);
	    // try to locate and select the current site
	    String this_site = Configuration.site_name;
	    for(int b = 0; b < site_combobox.getItemCount(); b++) {
		String entry = (String) site_combobox.getItemAt(b);
		if(this_site.equals(entry)) {
		    site_combobox.setSelectedIndex(b);
		    break;
		}
	    }

	    // just in case its not the current one?
	    current_site_selection = (String)site_combobox.getSelectedItem();

	    ArrayList servlet_options = Gatherer.servlet_config.getServletsForSite(current_site_selection);
	    if (servlet_options == null) {
		servlet_combobox.setToolTipText(Dictionary.get("Preferences.Connection.Servlet_Tooltip2"));
		//servlet_combobox.setModel(new DefaultComboBoxModel());
		servlet_combobox.setEnabled(false);
	    } else {
		///ystem.err.println(ArrayTools.objectArrayToString(servlet_options.toArray()));

		servlet_combobox.setModel(new DefaultComboBoxModel(servlet_options.toArray()));
		servlet_combobox.setToolTipText(Dictionary.get("Preferences.Connection.Servlet_Tooltip"));
		servlet_combobox.setEnabled(true);
		// try to locate and select the current servlet
		String this_servlet = Configuration.getServletPath();
		for(int b = 0; b < servlet_combobox.getItemCount(); b++) {
		    String entry = (String) servlet_combobox.getItemAt(b);
		    if(this_servlet.equals(entry)) {
			servlet_combobox.setSelectedIndex(b);
			break;
		    }
		}
		
	    }
	}
	
	boolean currently_enabled = Configuration.get("general.use_proxy", true);
	// Creation
	JPanel connection_pane = new JPanel();
	use_proxy_checkbox = new JCheckBox(Dictionary.get("Preferences.Connection.Use_Proxy"));
	use_proxy_checkbox.setSelected(currently_enabled);
	
	use_proxy_checkbox.setPreferredSize(ROW_SIZE);
	JPanel proxy_host_pane = new JPanel();
	proxy_host_pane.setPreferredSize(ROW_SIZE);
	JLabel proxy_host_label = new JLabel(Dictionary.get("Preferences.Connection.Proxy_Host"));
	proxy_host_label.setPreferredSize(LABEL_SIZE);
	
	proxy_host_field = new JTextField(Configuration.getString("general.proxy_host", true));
	proxy_host_field.setEnabled(currently_enabled);
	proxy_host_field.setToolTipText(Dictionary.get("Preferences.Connection.Proxy_Host_Tooltip"));
	
	JPanel proxy_port_pane = new JPanel();
	proxy_port_pane.setPreferredSize(ROW_SIZE);
	JLabel proxy_port_label = new JLabel(Dictionary.get("Preferences.Connection.Proxy_Port"));
	proxy_port_label.setPreferredSize(LABEL_SIZE);
	
	String port_value = Configuration.getString("general.proxy_port", true);
	if(port_value.length() > 0) {
	   proxy_port_field = new JSpinner(new SpinnerNumberModel((new Integer(port_value)).intValue(), 0, 65535, 1));
	}
	else {
	   proxy_port_field = new JSpinner(new SpinnerNumberModel(0, 0, 65535, 1));
	}
	proxy_port_field.setEnabled(currently_enabled);
	proxy_port_field.setToolTipText(Dictionary.get("Preferences.Connection.Proxy_Port_Tooltip"));
	
	// Connection
	use_proxy_checkbox.addActionListener(new UseProxyListener());
	if (Gatherer.GS3) {
	    site_combobox.addActionListener(new SiteComboboxListener());
	}

	// Layout
	program_pane.setLayout(new BorderLayout());
	program_pane.add(program_label, BorderLayout.WEST);
	program_pane.add(program_field, BorderLayout.CENTER);

	library_path_pane.setLayout(new BorderLayout());
	library_path_pane.add(library_path_label, BorderLayout.WEST);
	library_path_pane.add(library_path_field, BorderLayout.CENTER);

	if (Gatherer.isGsdlRemote) {
	    gliserver_url_pane.setLayout(new BorderLayout());
	    gliserver_url_pane.add(gliserver_url_label, BorderLayout.WEST);
	    gliserver_url_pane.add(gliserver_url_field, BorderLayout.CENTER);
	}

	if (Gatherer.GS3) {
	    site_pane.setLayout(new BorderLayout());
	    site_pane.add(site_label, BorderLayout.WEST);
	    site_pane.add(site_combobox, BorderLayout.CENTER);

	    servlet_pane.setLayout(new BorderLayout());
	    servlet_pane.add(servlet_label, BorderLayout.WEST);
	    servlet_pane.add(servlet_combobox, BorderLayout.CENTER);
	}

	proxy_host_pane.setLayout(new BorderLayout());
	proxy_host_pane.add(proxy_host_label, BorderLayout.WEST);
	proxy_host_pane.add(proxy_host_field, BorderLayout.CENTER);

	proxy_port_pane.setLayout(new BorderLayout());
	proxy_port_pane.add(proxy_port_label, BorderLayout.WEST);
	proxy_port_pane.add(proxy_port_field, BorderLayout.CENTER);

	connection_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
	connection_pane.setLayout(new GridLayout(8,1,0,2));
	connection_pane.add(program_pane);
	connection_pane.add(library_path_pane);
	if (Gatherer.isGsdlRemote) {
	    connection_pane.add(gliserver_url_pane);
	}
	if (Gatherer.GS3) {
	    connection_pane.add(site_pane);
	    connection_pane.add(servlet_pane);
	}
	connection_pane.add(use_proxy_checkbox);
	connection_pane.add(proxy_host_pane);
	connection_pane.add(proxy_port_pane);

	return connection_pane;
    }

    private JPanel createGeneralPreferences() {
	JPanel general_pane = new JPanel();

	// Build the model of available languages
	ArrayList dictionary_model = new ArrayList();

	// The new method makes use of the successor to the languages.dat file, classes/xml/languages.xml
	NodeList language_elements = LanguageManager.LANGUAGES_DOCUMENT.getDocumentElement().getElementsByTagName(StaticStrings.LANGUAGE_ELEMENT);
	for(int i = 0; i < language_elements.getLength(); i++) {
	    Element language_element = (Element) language_elements.item(i);
	    if((language_element.getAttribute(StaticStrings.GLI_ATTRIBUTE)).equalsIgnoreCase(StaticStrings.TRUE_STR) || (language_element.getAttribute(StaticStrings.MDS_ATTRIBUTE)).equalsIgnoreCase(StaticStrings.TRUE_STR)) {
		Locale locale = new Locale(language_element.getAttribute(StaticStrings.CODE_ATTRIBUTE));
		String description = language_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
		DictionaryEntry entry = new DictionaryEntry(description, locale);
		if(!dictionary_model.contains(entry)) {
		    dictionary_model.add(entry);
		}
		entry = null;
		description = null;
		locale = null;
	    }
	    language_element = null;
	}
	language_elements = null;

	// Users email
	JPanel email_pane = new JPanel();
	JLabel email_label = new JLabel(Dictionary.get("Preferences.General.Email"));
	email_label.setPreferredSize(LABEL_SIZE);
	email_field = new EmailField(Configuration.getColor("coloring.error_background", false));
	email_field.setText(Configuration.getEmail());
	email_field.setToolTipText(Dictionary.get("Preferences.General.Email_Tooltip"));
	
	// Font selection
	JPanel font_pane = new JPanel();
	JLabel font_label = new JLabel(Dictionary.get("Preferences.General.Font"));
	font_label.setPreferredSize(LABEL_SIZE);
	font_field = new JTextField(Configuration.getString("general.font", true));
	font_field.setToolTipText(Dictionary.get("Preferences.General.Font_Tooltip"));
	
	// Extracted metadata
	view_extracted_metadata_checkbox = new JCheckBox(Dictionary.get("Preferences.General.View_Extracted_Metadata"));
	view_extracted_metadata_checkbox.setSelected(false);
	if (Configuration.get("general.view_extracted_metadata", Configuration.COLLECTION_SPECIFIC)) {
	    view_extracted_metadata_checkbox.setSelected(true);
	}
	view_extracted_metadata_checkbox.setToolTipText(Dictionary.get("Preferences.General.View_Extracted_Metadata_Tooltip"));
	
	// Show file sizes
	show_file_size_checkbox = new JCheckBox(Dictionary.get("Preferences.General.Show_File_Size"));
	show_file_size_checkbox.setSelected(false);
	if (Configuration.get("general.show_file_size", Configuration.COLLECTION_SPECIFIC)) {
	    show_file_size_checkbox.setSelected(true);
	}
	show_file_size_checkbox.setToolTipText(Dictionary.get("Preferences.General.Show_File_Size_Tooltip"));
	
	// Language
	JPanel language_pane = new JPanel();
	JLabel language_label = new JLabel(Dictionary.get("Preferences.General.Interface_Language"));
	language_label.setPreferredSize(LABEL_SIZE);
	
	language_combobox = new JComboBox(dictionary_model.toArray());
	language_combobox.setOpaque(false);
	language_combobox.setToolTipText(Dictionary.get("Preferences.General.Interface_Language_Tooltip"));
	
	// Try to locate and select the current language
	String language_code = Configuration.getLanguage();
	for (int b = 0; b < language_combobox.getItemCount(); b++) {
	    DictionaryEntry entry = (DictionaryEntry) language_combobox.getItemAt(b);
	    if (language_code.equalsIgnoreCase(entry.getLocale().getLanguage())) {
		language_combobox.setSelectedIndex(b);
		break;
	    }
	}

	// Layout
	email_pane.setLayout(new BorderLayout());
	email_pane.add(email_label, BorderLayout.WEST);
	email_pane.add(email_field, BorderLayout.CENTER);

	language_pane.setLayout(new BorderLayout());
	language_pane.add(language_label, BorderLayout.WEST);
	language_pane.add(language_combobox, BorderLayout.CENTER);

	font_pane.setLayout(new BorderLayout());
	font_pane.add(font_label, BorderLayout.WEST);
	font_pane.add(font_field, BorderLayout.CENTER);

	general_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
	general_pane.setLayout(new GridLayout(5,1,0,5));
	general_pane.add(email_pane);
	general_pane.add(language_pane);
	general_pane.add(font_pane);
	general_pane.add(view_extracted_metadata_checkbox);
	general_pane.add(show_file_size_checkbox);

	return general_pane;
    }

    /** Generate the controls for altering the detail mode.
     * @return a JPanel of controls
     */
    private JPanel createModePreferences() {
	// Create Controls
	JPanel mode_panel = new JPanel();
	JPanel button_panel = new JPanel();
	ButtonGroup mode_button_group = new ButtonGroup();
	assistant_mode_radio_button = new JRadioButton(Dictionary.get("Preferences.Mode.Assistant"));
	assistant_mode_radio_button.setOpaque(false);
	mode_button_group.add(assistant_mode_radio_button);
	expert_mode_radio_button = new JRadioButton(Dictionary.get("Preferences.Mode.Expert"));
	expert_mode_radio_button.setOpaque(false);
	mode_button_group.add(expert_mode_radio_button);
	librarian_mode_radio_button = new JRadioButton(Dictionary.get("Preferences.Mode.Librarian"));
	librarian_mode_radio_button.setOpaque(false);
	mode_button_group.add(librarian_mode_radio_button);
	systems_mode_radio_button = new JRadioButton(Dictionary.get("Preferences.Mode.Systems"));
	systems_mode_radio_button.setOpaque(false);
	mode_button_group.add(systems_mode_radio_button);
	mode_description_textarea = new JTextArea();
	mode_description_textarea.setEditable(false);
	mode_description_textarea.setLineWrap(true);
	mode_description_textarea.setWrapStyleWord(true);
	// Determine which value is already selected
	switch(Configuration.getMode()) {
	case Configuration.ASSISTANT_MODE:
	    assistant_mode_radio_button.setSelected(true);
	    mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Assistant_Description"));
	    break;
	case Configuration.SYSTEMS_MODE:
	    systems_mode_radio_button.setSelected(true);
	    mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Systems_Description"));
	    break;
	case Configuration.EXPERT_MODE:
	    expert_mode_radio_button.setSelected(true);
	    mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Expert_Description"));
	    break;
	default:
	    librarian_mode_radio_button.setSelected(true);
	    mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Librarian_Description"));
	}
	// Connection - when a radio button is selected we have to change the description
	ModeRadioButtonListener listener = new ModeRadioButtonListener();
	assistant_mode_radio_button.addActionListener(listener);
	expert_mode_radio_button.addActionListener(listener);
	librarian_mode_radio_button.addActionListener(listener);
	systems_mode_radio_button.addActionListener(listener);
	listener = null;
	// Layout
	button_panel.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
	button_panel.setLayout(new GridLayout(4,1,2,2));
	button_panel.add(assistant_mode_radio_button);
	button_panel.add(librarian_mode_radio_button);
	button_panel.add(systems_mode_radio_button);
	button_panel.add(expert_mode_radio_button);

	mode_panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
	mode_panel.setLayout(new BorderLayout());
	mode_panel.add(button_panel, BorderLayout.NORTH);
	mode_panel.add(new JScrollPane(mode_description_textarea), BorderLayout.CENTER);

	return mode_panel;
    }


    /** The warning preferences are controlled through a checklist. */
    private JPanel createWarningPreferences()
    {
	warning_preferences_check_list = new CheckList(false);

	// Read all the warnings from the general xml/config.xml file, and their values from the user config.xml file
	Document general_config_xml_file_document = XMLTools.parseXMLFile("xml/config.xml", true);
	NodeList argument_elements_nodelist = general_config_xml_file_document.getDocumentElement().getElementsByTagName("Argument");
	for (int i = 0; i < argument_elements_nodelist.getLength(); i++) {
	    Element argument_element = (Element) argument_elements_nodelist.item(i);
	    String argument_element_name = argument_element.getAttribute("name");
	    if (argument_element_name.startsWith("warning.")) {
		String warning_title = Dictionary.get(argument_element_name.substring("warning.".length()) + ".Title");
		boolean warning_enabled = Configuration.get(argument_element_name, true);
		CheckListEntry warning_entry = new CheckListEntry(warning_title, warning_enabled);
		warning_entry.setProperty(argument_element_name);
		warning_preferences_check_list.addEntry(warning_entry);
	    }
	}

	JPanel warning_preferences_pane = new JPanel();
	warning_preferences_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
	warning_preferences_pane.setLayout(new BorderLayout());
	warning_preferences_pane.add(new JScrollPane(warning_preferences_check_list), BorderLayout.CENTER);
	return warning_preferences_pane;
    }


    private JPanel createWorkflowPreferences() {
	// Read in the predefined configurations file
	Vector predefined = new Vector();
	Document predefined_document = XMLTools.parseXMLFile("xml/workflows.xml", true);
	Element predefined_element = predefined_document.getDocumentElement();
	NodeList workflow_elements = predefined_element.getElementsByTagName("Workflow");
	for(int i = 0; i < workflow_elements.getLength(); i++) {
	    predefined.add(new WorkflowElementWrapper((Element)workflow_elements.item(i)));
	}

	// Creation
	JPanel workflow_preferences_pane = new JPanel();
	JPanel checklist_pane = new JPanel();
	JLabel title_label = new JLabel(Dictionary.get("Preferences.Workflow.Title"));
	title_label.setPreferredSize(ROW_SIZE);
	
	workflow_download = new JCheckBox(Dictionary.get("GUI.Download")+" - "+Dictionary.get("GUI.Download_Tooltip"));
	workflow_download.setSelected(Configuration.get("workflow.download", false));
	workflow_download.setPreferredSize(ROW_SIZE);
	
	workflow_gather = new JCheckBox(Dictionary.get("GUI.Gather")+" - "+Dictionary.get("GUI.Gather_Tooltip"));
	workflow_gather.setSelected(Configuration.get("workflow.gather", false));
	workflow_gather.setPreferredSize(ROW_SIZE);
	
	workflow_enrich = new JCheckBox(Dictionary.get("GUI.Enrich")+" - "+Dictionary.get("GUI.Enrich_Tooltip"));
	workflow_enrich.setSelected(Configuration.get("workflow.enrich", false));
	workflow_enrich.setPreferredSize(ROW_SIZE);
	
	workflow_design = new JCheckBox(Dictionary.get("GUI.Design")+" - "+Dictionary.get("GUI.Design_Tooltip"));
	workflow_design.setSelected(Configuration.get("workflow.design", false));
	workflow_design.setPreferredSize(ROW_SIZE);
	
	workflow_create = new JCheckBox(Dictionary.get("GUI.Create")+" - "+Dictionary.get("GUI.Create_Tooltip"));
	workflow_create.setSelected(Configuration.get("workflow.create", false));
	workflow_create.setPreferredSize(ROW_SIZE);
	

	workflow_format = new JCheckBox(Dictionary.get("GUI.Format")+" - "+Dictionary.get("GUI.Format_Tooltip"));
	workflow_format.setSelected(Configuration.get("workflow.format", false));
	workflow_format.setPreferredSize(ROW_SIZE);
	
	JPanel predefined_pane = new JPanel();
	JLabel predefined_label = new JLabel(Dictionary.get("Preferences.Workflow.Predefined.Label"));
	JComboBox predefined_combobox = new JComboBox(predefined);
	predefined_combobox.setOpaque(false);
	// Connection
	predefined_combobox.addActionListener(new PredefinedActionListener());

	// Layout
	checklist_pane.setLayout(new BoxLayout(checklist_pane, BoxLayout.Y_AXIS));
	checklist_pane.add(title_label);
	if (Configuration.get("workflow.download", true)) {
	    checklist_pane.add(workflow_download);
	}
	if (Configuration.get("workflow.gather", true)) {
	    checklist_pane.add(workflow_gather);
	}
	if (Configuration.get("workflow.enrich", true)) {
	    checklist_pane.add(workflow_enrich);
	}
	if (Configuration.get("workflow.design", true)) {
	    checklist_pane.add(workflow_design);
	}
	if (Configuration.get("workflow.create", true)) {
	    checklist_pane.add(workflow_create);
	}
	if (Configuration.get("workflow.format", true)) {
	    checklist_pane.add(workflow_format);
	}
	
	predefined_pane.setLayout(new BorderLayout(5,0));
	predefined_pane.add(predefined_label, BorderLayout.WEST);
	predefined_pane.add(predefined_combobox, BorderLayout.CENTER);

	workflow_preferences_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
	workflow_preferences_pane.setLayout(new BorderLayout());
	workflow_preferences_pane.add(checklist_pane, BorderLayout.CENTER);
	workflow_preferences_pane.add(predefined_pane, BorderLayout.SOUTH);

	return workflow_preferences_pane;
    }


    private class OKButtonListener
	implements ActionListener {
	private boolean close;
	public OKButtonListener(boolean close) {
	    this.close = close;
	}
	public void actionPerformed(ActionEvent event)
	{
	    // Connection preferences
	    String program_str = program_field.getText();
	    if (program_str.length() > 0 && program_str.indexOf("%1") == -1) {
		program_str = program_str + " %1";
	    }
	    Configuration.setPreviewCommand(program_str);

	    String library_url_string = library_path_field.getText();
	    if (library_url_string.equals("")) {
		Configuration.library_url = null;
	    }
	    else {
		try {
		    Configuration.library_url = new URL(library_url_string);
		}
		catch (MalformedURLException exception) {
		    DebugStream.printStackTrace(exception);
		}
	    }
	    Configuration.setString("general.library_url", true, library_url_string);

	    if (Gatherer.isGsdlRemote) {
		String gliserver_url_string = gliserver_url_field.getText();
		if (gliserver_url_string.equals("")) {
		    Configuration.gliserver_url = null;
		}
		else {
		    try {
			Configuration.gliserver_url = new URL(gliserver_url_string);
		    }
		    catch (MalformedURLException exception) {
			DebugStream.printStackTrace(exception);
		    }
		}
		Configuration.setString("general.gliserver_url", true, gliserver_url_string);
	    }

	    boolean site_changed = false;
	    if (Gatherer.GS3) {
		String current_site = Configuration.site_name;
		String new_site =(String)site_combobox.getSelectedItem() ;
		if (!new_site.equals(current_site)) {
		    site_changed = true;
		}
		Configuration.setSiteAndServlet(new_site, (String)servlet_combobox.getSelectedItem());
	    }

	    Configuration.set("general.use_proxy", true, use_proxy_checkbox.isSelected());
	    Configuration.setString("general.proxy_host", true, proxy_host_field.getText());
	    Configuration.setString("general.proxy_port", true, proxy_port_field.getValue() + "");
	    Gatherer.setProxy();

	    // General preferences
	    Configuration.setEmail(email_field.getText());
	    Configuration.set("general.show_file_size", Configuration.COLLECTION_SPECIFIC, show_file_size_checkbox.isSelected());
	    Configuration.set("general.view_extracted_metadata", Configuration.COLLECTION_SPECIFIC, view_extracted_metadata_checkbox.isSelected());

	    // Two options requiring restarting the GLI to apply: interface font, and interface language
	    boolean restart_required = false;

	    // GLI interface font
	    String current_font = Configuration.getString("general.font", true);
	    if (!current_font.equals(font_field.getText())) {
		Configuration.setString("general.font", true, font_field.getText());
		restart_required = true;
	    }

	    // GLI interface language
	    String current_lang = Configuration.getLanguage();
	    if (!current_lang.equals(((DictionaryEntry) language_combobox.getSelectedItem()).getLocale().getLanguage())) {
		Configuration.setLocale("general.locale", Configuration.GENERAL_SETTING, ((DictionaryEntry) language_combobox.getSelectedItem()).getLocale());
		restart_required = true;
	    }

	    // Inform the user that a restart is required, if necessary
	    if (restart_required) {
		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Preferences.General.Restart_Required"), Dictionary.get("General.Warning"), JOptionPane.WARNING_MESSAGE);
	    }

	    // Mode preferences
	    int current_mode = Configuration.getMode();
	    int new_mode;
	    if (assistant_mode_radio_button.isSelected()) {
		new_mode = Configuration.ASSISTANT_MODE;
	    }
	    else if (systems_mode_radio_button.isSelected()) {
		new_mode = Configuration.SYSTEMS_MODE;
	    }
	    else if (expert_mode_radio_button.isSelected()) {
		new_mode = Configuration.EXPERT_MODE;
	    }
	    else {
		new_mode = Configuration.LIBRARIAN_MODE;
	    }

	    // If there has been a change in modes, update the config, and also inform the persistant gui views that have a need to know
	    if (new_mode != current_mode) {
		Configuration.setMode(new_mode);
		Collection collection = Gatherer.c_man.getCollection();
		if (collection != null) {
		    collection.cdm.modeChanged(new_mode);
		}
		Gatherer.g_man.modeChanged(new_mode);
	    }

	    // Warning preferences
	    ListModel warning_preferences_check_list_model = warning_preferences_check_list.getModel();
	    for (int i = 0; i < warning_preferences_check_list_model.getSize(); i++) {
		CheckListEntry entry = (CheckListEntry) warning_preferences_check_list_model.getElementAt(i);
		Configuration.set(entry.getProperty(), true, entry.isSelected());
	    }

	    if (Gatherer.GS3 && site_changed && Gatherer.c_man.getCollection() != null) {
		// shut down the collection
		System.err.println("shutting down teh collection");
		Gatherer.g_man.saveThenCloseCurrentCollection();
	    }

	    // Workflow preferences
// 	    Configuration.set("workflow.download", false, workflow_download.isSelected());
// 	    Configuration.set("workflow.gather", false, workflow_gather.isSelected());
// 	    Configuration.set("workflow.enrich", false, workflow_enrich.isSelected());
// 	    Configuration.set("workflow.design", false, workflow_design.isSelected());
// 	    Configuration.set("workflow.create", false, workflow_create.isSelected());
// 	    Configuration.set("workflow.format", false, workflow_format.isSelected());
	    
// 	    Gatherer.g_man.workflowUpdate("Download", workflow_download.isSelected());
// 	    Gatherer.g_man.workflowUpdate("Gather", workflow_gather.isSelected());
// 	    Gatherer.g_man.workflowUpdate("Enrich", workflow_enrich.isSelected());
// 	    Gatherer.g_man.workflowUpdate("Design", (workflow_design.isSelected() && Configuration.getMode() > Configuration.ASSISTANT_MODE));
// 	    Gatherer.g_man.workflowUpdate("Create", workflow_create.isSelected());
// 	    Gatherer.g_man.workflowUpdate("Format", workflow_format.isSelected());

	    // Always save configuration changes immediately (in case the GLI crashes)
	    Configuration.save();

	    // Refresh the GLI to account for the configuration changes
	    Gatherer.refresh(Gatherer.PREFERENCES_CHANGED);

	    // Hide dialog
	    if (close) {
		self.dispose();
	    }

	    if (restart_required) {
		Gatherer.g_man.exit(Gatherer.EXIT_THEN_RESTART);
	    }
	}
    }

    private class CancelButtonListener
	implements ActionListener {
	public void actionPerformed(ActionEvent event) {
	    self.dispose();
	}
    }

    private class DictionaryEntry
	implements Comparable {
	private Locale locale;
	private String description;
	public DictionaryEntry(Locale locale) {
	    this.description = null;
	    this.locale = locale;
	}
	public DictionaryEntry(String description, Locale locale) {
	    this.description = description;
	    this.locale = locale;
	}
	public int compareTo(Object object) {
	    return toString().compareTo(object.toString());
	}
	public boolean equals(Object object) {
	    return toString().equals(object.toString());
	}
	public Locale getLocale() {
	    return locale;
	}
	public String toString() {
	    if(description != null) {
		return description;
	    }
	    else {
		return locale.getDisplayName();
	    }
	}
    }

    /** This listener updates the mode description depending on what mode is selected. */
    private class ModeRadioButtonListener
	implements ActionListener {
	public void actionPerformed(ActionEvent event) {
	    Object source = event.getSource();
	    if(source == assistant_mode_radio_button) {
		mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Assistant_Description"));
	    }
	    else if(source == expert_mode_radio_button) {
		mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Expert_Description"));
	    }
	    else if(source == systems_mode_radio_button) {
		mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Systems_Description"));
	    }
	    else {
		mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Librarian_Description"));
	    }
	    source = null;
	}
    }

    private class PredefinedActionListener
	implements ActionListener {
	public void actionPerformed(ActionEvent event) {
	    JComboBox cb = (JComboBox) event.getSource();
	    WorkflowElementWrapper element = (WorkflowElementWrapper) cb.getSelectedItem();
	    CheckboxUpdater task = new CheckboxUpdater(element);
	    SwingUtilities.invokeLater(task);
	}

	private class CheckboxUpdater
	    implements Runnable {
	    private WorkflowElementWrapper element;
	    public CheckboxUpdater(WorkflowElementWrapper element) {
		this.element = element;
	    }
	    public void run() {
		workflow_download.setSelected(element.getEnabled("download"));
		workflow_gather.setSelected(element.getEnabled("gather"));
		workflow_enrich.setSelected(element.getEnabled("enrich"));
		workflow_design.setSelected(element.getEnabled("design"));
		workflow_create.setSelected(element.getEnabled("create"));
		workflow_format.setSelected(element.getEnabled("format"));
	    }
	}
    }


    private class SiteComboboxListener
	implements ActionListener {
	private boolean ignore_event=false;
	public void actionPerformed(ActionEvent event) {
	    System.err.println("event occurred "+event.paramString());
	    String site = (String) site_combobox.getSelectedItem();
	    System.err.println("new site = "+site);
	    if (!site.equals(current_site_selection)) {
		current_site_selection = site;
		System.err.println("changed the current selection");
		ArrayList servlet_options = Gatherer.servlet_config.getServletsForSite(current_site_selection);
		if (servlet_options == null) {
		    ///ystem.err.println("no servlets for this site");
		    servlet_combobox.setModel(new DefaultComboBoxModel());
		    servlet_combobox.setToolTipText(Dictionary.get("Preferences.Connection.Servlet_Tooltip2"));
		    servlet_combobox.setEnabled(false);

		} else {
		    ///ystem.err.println(ArrayTools.objectArrayToString(servlet_options.toArray()));
		    servlet_combobox.setModel(new DefaultComboBoxModel(servlet_options.toArray()));
		    servlet_combobox.setToolTipText(Dictionary.get("Preferences.Connection.Servlet_Tooltip"));
		    servlet_combobox.setEnabled(true);
		}
	    }
	}    
    }

    private class UseProxyListener
	implements ActionListener {
	public void actionPerformed(ActionEvent event) {
	    boolean enabled = use_proxy_checkbox.isSelected();
	    Configuration.set("general.use_proxy", true, enabled);
	    // Fortunately this is already driven by the event thread.
	    proxy_host_field.setEnabled(enabled);
	    proxy_port_field.setEnabled(enabled);
	}
    }

    private class WorkflowElementWrapper {
	private Element element;
	private String text;
	public WorkflowElementWrapper(Element element) {
	    this.element = element;
	}
	public boolean getEnabled(String name) {
	    boolean result = true;
	    if(element.getAttribute(name).equalsIgnoreCase("false")) {
		result = false;
	    }
	    return result;
	}
	public String toString() {
	    if (text == null) {
		text = Dictionary.get(element.getFirstChild().getNodeValue());
	    }
	    return text;
	}
    }
}
