/**
 *#########################################################################
 *
 * 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.remote.RemoteGreenstoneServer;
import org.greenstone.gatherer.Configuration;
import org.greenstone.gatherer.GAuthenticator;
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 HTTP = "HTTP";
    static final public String HTTPS = "HTTPS";
    static final public String FTP = "FTP";
    
    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 chdir_button;
    private JButton ok_button;
    private JCheckBox show_file_size_checkbox;
    private JCheckBox no_check_certificate_checkbox; // Set no_check_certificate when retrieving https URLs that have no (valid) certificate
    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 JCheckBox workflow_files;
    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 JSpinner http_proxy_port_field;
    private JSpinner https_proxy_port_field;
    private JSpinner ftp_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 http_proxy_host_field;
    private JTextField https_proxy_host_field;
    private JTextField ftp_proxy_host_field;
    private JTextField collect_dir_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();
        content_pane.setComponentOrientation(Dictionary.getOrientation());
	tab_pane = new JTabbedPane();
        tab_pane.setComponentOrientation(Dictionary.getOrientation());
	JPanel general_preferences = createGeneralPreferences();
        general_preferences.setComponentOrientation(Dictionary.getOrientation());
	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();
        connection_preferences.setComponentOrientation(Dictionary.getOrientation());
	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();
        button_pane.setComponentOrientation(Dictionary.getOrientation());
	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);
        button_pane.setComponentOrientation(Dictionary.getOrientation());
        
	content_pane.setLayout(new BorderLayout());
	content_pane.add(tab_pane, BorderLayout.CENTER);
	content_pane.add(button_pane, BorderLayout.SOUTH);
        content_pane.setComponentOrientation(Dictionary.getOrientation());
        
	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 if not in GLI GUI test mode
	// If in test mode, I need widgets like tab_pane and buttons to exist
	if(!TestingPreparation.TEST_MODE) {
	    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;
	}

	TestingPreparation.setNamesRecursively(this);
	
	setVisible(true);
    }

    private JPanel createConnectionPreferences() {
	JPanel program_pane = new JPanel();
        program_pane.setComponentOrientation(Dictionary.getOrientation());
	program_pane.setPreferredSize(ROW_SIZE);
	JLabel program_label = new JLabel(Dictionary.get("Preferences.Connection.ProgramCommand"));
	program_label.setPreferredSize(LABEL_SIZE);
	program_label.setComponentOrientation(Dictionary.getOrientation());
        
	program_field = new JTextField(Configuration.getPreviewCommand());
	program_field.setCaretPosition(0);
	program_field.setToolTipText(Dictionary.get("Preferences.Connection.ProgramCommand_Tooltip"));
	program_field.setComponentOrientation(Dictionary.getOrientation());
        
	JPanel library_path_pane = new JPanel();
	library_path_pane.setPreferredSize(ROW_SIZE);
        library_path_pane.setComponentOrientation(Dictionary.getOrientation());
	JLabel library_path_label = new JLabel();
	library_path_label.setPreferredSize(LABEL_SIZE);
        library_path_label.setComponentOrientation(Dictionary.getOrientation());
	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);
        library_path_field.setComponentOrientation(Dictionary.getOrientation());
	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 or webswing, as it is automatically determined
	library_path_field.setEnabled(!(Gatherer.isApplet || Gatherer.isWebswing));

	JPanel gliserver_url_pane = null;
	JLabel gliserver_url_label = null;
	if (Gatherer.isGsdlRemote && !Gatherer.GS3) {
	    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);
            gliserver_url_label.setComponentOrientation(Dictionary.getOrientation());
	    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.setComponentOrientation(Dictionary.getOrientation());
	    gliserver_url_field.setCaretPosition(0);
	    gliserver_url_field.setToolTipText(Dictionary.get("Preferences.Connection.GLIServer_URL_Tooltip"));
	   
	    // Disable this field when using the applet or webswing, as it is automatically determined
	    gliserver_url_field.setEnabled(!(Gatherer.isApplet || Gatherer.isWebswing));
	}

	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_pane.setComponentOrientation(Dictionary.getOrientation());
	    site_label = new JLabel(Dictionary.get("Preferences.Connection.Site"));
	    site_label.setPreferredSize(LABEL_SIZE);
            site_label.setComponentOrientation(Dictionary.getOrientation());
	    // 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"));
	    site_combobox.setComponentOrientation(Dictionary.getOrientation());
            
	    servlet_pane = new JPanel();
	    servlet_pane.setPreferredSize(ROW_SIZE);
            servlet_pane.setComponentOrientation(Dictionary.getOrientation());
            
	    servlet_label = new JLabel(Dictionary.get("Preferences.Connection.Servlet"));
	    servlet_label.setPreferredSize(LABEL_SIZE);
            servlet_label.setComponentOrientation(Dictionary.getOrientation());
	    servlet_combobox = new JComboBox();
	    servlet_combobox.setOpaque(false);
            servlet_combobox.setComponentOrientation(Dictionary.getOrientation());
	    // 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;
		    }
		}
		
	    }

            if (Gatherer.isWebswing) {
              site_combobox.setEnabled(false);
              servlet_combobox.setEnabled(false);
            }
        }

	JPanel collect_dir_pane = new JPanel();
        collect_dir_pane.setComponentOrientation(Dictionary.getOrientation());
	collect_dir_pane.setPreferredSize(ROW_SIZE);
	JLabel collect_dir_label = new JLabel(Dictionary.get("Preferences.Connection.CollectDirectory"));
	collect_dir_label.setPreferredSize(LABEL_SIZE);
	collect_dir_label.setComponentOrientation(Dictionary.getOrientation());
	collect_dir_field = new JTextField(Gatherer.getCollectDirectoryPath());
	//collect_dir_field = new JTextField(Configuration.getString("general.open_collection"+Configuration.gliPropertyNameSuffix(), true));
	collect_dir_field.setCaretPosition(0);
	collect_dir_field.setToolTipText(Dictionary.get("Preferences.Connection.CollectDirectory_Tooltip"));
	collect_dir_field.setEditable(false);
	JButton chdir_button = new GLIButton(Dictionary.get("General.CD"), Dictionary.get("General.CD_Tooltip"));
	chdir_button.addActionListener(new ChangeDirListener());
	if(Gatherer.isGsdlRemote || Gatherer.isWebswing) { // disable changing directories for client GLI
          collect_dir_field.setEnabled(false);
          chdir_button.setEnabled(false);
	}

	boolean no_check_cert_enabled = Configuration.get("general.no_check_certificate", true); // pass true to look in general rather than collection specific config file
	
	boolean currently_enabled = Configuration.get("general.use_proxy", true);
	// Creation
	JPanel connection_pane = new JPanel();
        connection_pane.setComponentOrientation(Dictionary.getOrientation());
	no_check_certificate_checkbox = new JCheckBox(Dictionary.get("Preferences.Connection.No_Check_Certificate"));
	no_check_certificate_checkbox.setToolTipText(Dictionary.get("Preferences.Connection.No_Check_Certificate_Tooltip"));
	no_check_certificate_checkbox.setSelected(no_check_cert_enabled);
	no_check_certificate_checkbox.setComponentOrientation(Dictionary.getOrientation());        
	no_check_certificate_checkbox.setPreferredSize(ROW_SIZE);
	
	use_proxy_checkbox = new JCheckBox(Dictionary.get("Preferences.Connection.Use_Proxy"));
	use_proxy_checkbox.setSelected(currently_enabled);
	use_proxy_checkbox.setComponentOrientation(Dictionary.getOrientation());        
	use_proxy_checkbox.setPreferredSize(ROW_SIZE);
	
	
	// Connection
	no_check_certificate_checkbox.addActionListener(new NoCheckCertificateListener());
	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.LINE_START);
	program_pane.add(program_field, BorderLayout.CENTER);

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

	if (Gatherer.isGsdlRemote && !Gatherer.GS3) {
	    gliserver_url_pane.setLayout(new BorderLayout());
	    gliserver_url_pane.add(gliserver_url_label, BorderLayout.LINE_START);
	    gliserver_url_pane.add(gliserver_url_field, BorderLayout.CENTER);
	}

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

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

	collect_dir_pane.setLayout(new BorderLayout());
	collect_dir_pane.add(collect_dir_label, BorderLayout.LINE_START);
	collect_dir_pane.add(collect_dir_field, BorderLayout.CENTER);
	collect_dir_pane.add(chdir_button, BorderLayout.LINE_END);


	connection_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
	connection_pane.setLayout(new GridLayout(10,1,0,2));
        if (!Gatherer.isWebswing) {
          connection_pane.add(program_pane);
        }
	connection_pane.add(library_path_pane);
	if (Gatherer.isGsdlRemote && !Gatherer.GS3) {
	    connection_pane.add(gliserver_url_pane);
	}
	if (Gatherer.GS3) {
	    connection_pane.add(site_pane);
	    connection_pane.add(servlet_pane);
	}
	connection_pane.add(collect_dir_pane);

	connection_pane.add(no_check_certificate_checkbox);
	connection_pane.add(use_proxy_checkbox);
	
	// set up the proxy host and port fields for each of http, https and ftp	
        setupProxyHostPane(HTTP, connection_pane, currently_enabled, http_proxy_host_field, http_proxy_port_field);
	setupProxyHostPane(HTTPS, connection_pane, currently_enabled, https_proxy_host_field, https_proxy_port_field);
	setupProxyHostPane(FTP, connection_pane, currently_enabled, ftp_proxy_host_field, ftp_proxy_port_field);

	return connection_pane;
    }

    private JPanel createGeneralPreferences() {
	JPanel general_pane = new JPanel();
        general_pane.setComponentOrientation(Dictionary.getOrientation());
	// 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.hasAttribute(StaticStrings.GLI_ATTRIBUTE) 
		&& (language_element.getAttribute(StaticStrings.GLI_ATTRIBUTE)).equalsIgnoreCase(StaticStrings.TRUE_STR)) 
	       || (language_element.hasAttribute(StaticStrings.MDS_ATTRIBUTE) 
		   && (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();
        email_pane.setComponentOrientation(Dictionary.getOrientation());

        JLabel email_label = new JLabel(Dictionary.get("Preferences.General.Email"));
        email_label.setComponentOrientation(Dictionary.getOrientation());
	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"));
	email_field.setComponentOrientation(Dictionary.getOrientation());
	// Font selection
	JPanel font_pane = new JPanel();
        font_pane.setComponentOrientation(Dictionary.getOrientation());
	
        JLabel font_label = new JLabel(Dictionary.get("Preferences.General.Font"));
        font_label.setComponentOrientation(Dictionary.getOrientation());
	font_label.setPreferredSize(LABEL_SIZE);
	
        font_field = new JTextField(Configuration.getString("general.font", true));
	font_field.setToolTipText(Dictionary.get("Preferences.General.Font_Tooltip"));
	font_field.setComponentOrientation(Dictionary.getOrientation());
        
	// Extracted metadata
	view_extracted_metadata_checkbox = new JCheckBox(Dictionary.get("Preferences.General.View_Extracted_Metadata"));
	view_extracted_metadata_checkbox.setSelected(false);
        view_extracted_metadata_checkbox.setComponentOrientation(Dictionary.getOrientation());
	
        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"));
        view_extracted_metadata_checkbox.setComponentOrientation(Dictionary.getOrientation());
        
	// Show file sizes
	show_file_size_checkbox = new JCheckBox(Dictionary.get("Preferences.General.Show_File_Size"));
	show_file_size_checkbox.setSelected(false);
        show_file_size_checkbox.setComponentOrientation(Dictionary.getOrientation());
        
	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();
        language_pane.setComponentOrientation(Dictionary.getOrientation());

        JLabel language_label = new JLabel(Dictionary.get("Preferences.General.Interface_Language"));
        language_label.setComponentOrientation(Dictionary.getOrientation());
	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"));
	language_combobox.setComponentOrientation(Dictionary.getOrientation());
        
	// Try to locate and select the current language
	// Else default to English
	String language_code = Configuration.getLanguage();
	int defaultIndex = 0;
	DictionaryEntry defaultEntry = null;

	int b = 0;
	for (; b < language_combobox.getItemCount(); b++) {
	    DictionaryEntry entry = (DictionaryEntry) language_combobox.getItemAt(b);
	    if (language_code.equalsIgnoreCase(entry.getLocale().getLanguage())) {
		language_combobox.setSelectedIndex(b);
		break;
	    } else if (entry.getLocale().getLanguage().equalsIgnoreCase("en")) { // store English as fallback
		defaultIndex = b;
		defaultEntry = entry;
	    }
	}
	// if we cycled through and couldn't find the chosen language to load, 
	// then we set the Preferences' and Configuration's language to English
	if (b == language_combobox.getItemCount()) {
	    language_combobox.setSelectedIndex(defaultIndex);
	    Configuration.setLocale("general.locale", true, defaultEntry.getLocale());
	    System.err.println("*** GLI doesn't yet support the language: " + language_code 
			       + " and has therefore defaulted to: " + Configuration.getLanguage());
	}
        // webswing - can't change these.
        if(Gatherer.isWebswing) {
          language_combobox.setToolTipText(Dictionary.get("Preferences.General.Interface_Language_Tooltip_Webswing"));
          language_combobox.setEnabled(false);
          font_field.setEnabled(false);
        }
	// Layout
	email_pane.setLayout(new BorderLayout());
	email_pane.add(email_label, BorderLayout.LINE_START);
	email_pane.add(email_field, BorderLayout.CENTER);

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

	font_pane.setLayout(new BorderLayout());
	font_pane.add(font_label, BorderLayout.LINE_START);
	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;
    }

    private void setupProxyHostPane(String protocol, JPanel connection_pane, boolean isEnabled,
				    JTextField proxy_host_field, JSpinner proxy_port_field)
    {
	final Dimension WIDER_LABEL_SIZE = new Dimension(180, 25);
	final Dimension NARROWER_LABEL_SIZE = new Dimension(60, 25);
	final Dimension WIDER_ROW_SIZE = new Dimension(480, 25);
	final Dimension NARROWER_ROW_SIZE = new Dimension(120, 25);
	
	JPanel proxy_host_pane = new JPanel();
        proxy_host_pane.setComponentOrientation(Dictionary.getOrientation());
	proxy_host_pane.setPreferredSize(WIDER_ROW_SIZE);
        
	JLabel proxy_host_label = new JLabel(Dictionary.get("Preferences.Connection."+protocol+"_Proxy_Host"));
        proxy_host_label.setComponentOrientation(Dictionary.getOrientation());
	proxy_host_label.setPreferredSize(WIDER_LABEL_SIZE);
	
	proxy_host_field = new JTextField(Configuration.getString("general."+protocol+"_proxy_host", true));
	proxy_host_field.setEnabled(isEnabled);
	proxy_host_field.setToolTipText(Dictionary.get("Preferences.Connection."+protocol+"_Proxy_Host_Tooltip"));
	proxy_host_field.setComponentOrientation(Dictionary.getOrientation());
        
	JPanel proxy_port_pane = new JPanel();
        proxy_port_pane.setComponentOrientation(Dictionary.getOrientation());
	proxy_port_pane.setPreferredSize(NARROWER_ROW_SIZE);
        
	JLabel proxy_port_label = new JLabel(Dictionary.get("Preferences.Connection.Proxy_Port"));
	proxy_port_label.setPreferredSize(NARROWER_LABEL_SIZE);
        proxy_port_label.setComponentOrientation(Dictionary.getOrientation());
	
	String port_value = Configuration.getString("general."+protocol+"_proxy_port", true);
	if(port_value.length() > 0) {
	   proxy_port_field = new JSpinner(new SpinnerNumberModel((Integer.valueOf(port_value)).intValue(), 0, 65535, 1));
	}
	else {
	   proxy_port_field = new JSpinner(new SpinnerNumberModel(0, 0, 65535, 1));
	}
	proxy_port_field.setEnabled(isEnabled);
	proxy_port_field.setToolTipText(Dictionary.get("Preferences.Connection."+protocol+"_Proxy_Port_Tooltip"));


	// Since the actual object member vars were null when this method is called
	// need to ensure they are assigned the correct value now, else those refs will remain null
	if(protocol.equals(HTTP)) {
	    http_proxy_host_field = proxy_host_field;
	    http_proxy_port_field = proxy_port_field;
	} else if (protocol.equals(HTTPS)) {
	    https_proxy_host_field = proxy_host_field;
	    https_proxy_port_field = proxy_port_field;
	} else if(protocol.equals(FTP)) {
	    ftp_proxy_host_field = proxy_host_field;
	    ftp_proxy_port_field = proxy_port_field;
	} 
	
	proxy_host_pane.setLayout(new BorderLayout());
	proxy_host_pane.add(proxy_host_label, BorderLayout.LINE_START);
	proxy_host_pane.add(proxy_host_field, BorderLayout.CENTER);

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

	//connection_pane.add(proxy_host_pane);
	//connection_pane.add(proxy_port_pane);

	JPanel proxy_panel = new JPanel();
	proxy_panel.setLayout(new BorderLayout());	
	proxy_panel.add(proxy_host_pane, BorderLayout.WEST);
	proxy_panel.add(proxy_port_pane, BorderLayout.CENTER);

	connection_pane.add(proxy_panel);
    }
    

    /** Generate the controls for altering the detail mode.
     * @return a JPanel of controls
     */
    private JPanel createModePreferences() {
	// Create Controls
	JPanel mode_panel = new JPanel();
        mode_panel.setComponentOrientation(Dictionary.getOrientation());
	
        JPanel button_panel = new JPanel();
        button_panel.setComponentOrientation(Dictionary.getOrientation());
	
        ButtonGroup mode_button_group = new ButtonGroup();
	
        assistant_mode_radio_button = new JRadioButton(Dictionary.get("Preferences.Mode.Assistant"));
	assistant_mode_radio_button.setOpaque(false);
        assistant_mode_radio_button.setComponentOrientation(Dictionary.getOrientation());
	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);
        expert_mode_radio_button.setComponentOrientation(Dictionary.getOrientation());
	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);
        librarian_mode_radio_button.setComponentOrientation(Dictionary.getOrientation());
	mode_button_group.add(librarian_mode_radio_button);
	
	
        mode_description_textarea = new JTextArea();
        mode_description_textarea.setComponentOrientation(Dictionary.getOrientation());
	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.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);
	listener = null;
	// Layout
	button_panel.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
	button_panel.setLayout(new GridLayout(3,1,2,2));
	button_panel.add(assistant_mode_radio_button);
	button_panel.add(librarian_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);
        warning_preferences_check_list.setComponentOrientation(Dictionary.getOrientation());

	// 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.setComponentOrientation(Dictionary.getOrientation());
	warning_preferences_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
	warning_preferences_pane.setLayout(new BorderLayout());
        JScrollPane scrol_tmp = new JScrollPane(warning_preferences_check_list);
        scrol_tmp.setComponentOrientation(Dictionary.getOrientation());
	warning_preferences_pane.add(scrol_tmp, 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();
        workflow_preferences_pane.setComponentOrientation(Dictionary.getOrientation());
	
        JPanel checklist_pane = new JPanel();
        checklist_pane.setComponentOrientation(Dictionary.getOrientation());
	
        JLabel title_label = new JLabel(Dictionary.get("Preferences.Workflow.Title"));
        title_label.setComponentOrientation(Dictionary.getOrientation());
	title_label.setPreferredSize(ROW_SIZE);
	
	workflow_download = new JCheckBox(Dictionary.get("GUI.Download")+" - "+Dictionary.get("GUI.Download_Tooltip"));
        workflow_download.setComponentOrientation(Dictionary.getOrientation());
	workflow_download.setSelected(Configuration.get("workflow.download", false) && Gatherer.isDownloadEnabled);
	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_gather.setComponentOrientation(Dictionary.getOrientation());
        
	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_enrich.setComponentOrientation(Dictionary.getOrientation());
        
	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_design.setComponentOrientation(Dictionary.getOrientation());
        
	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_create.setComponentOrientation(Dictionary.getOrientation());
        
	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);
	workflow_format.setComponentOrientation(Dictionary.getOrientation());
 	workflow_files = new JCheckBox(Dictionary.get("GUI.Files")+" - "+Dictionary.get("GUI.Files_Tooltip"));
	workflow_files.setSelected(Configuration.get("workflow.files", false));
	workflow_files.setPreferredSize(ROW_SIZE);
	workflow_files.setComponentOrientation(Dictionary.getOrientation());
       
	JPanel predefined_pane = new JPanel();
        predefined_pane.setComponentOrientation(Dictionary.getOrientation());
	
        JLabel predefined_label = new JLabel(Dictionary.get("Preferences.Workflow.Predefined.Label"));
        predefined_label.setComponentOrientation(Dictionary.getOrientation());
	
        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);
	}
	if (Configuration.get("workflow.files", true)) {
	    checklist_pane.add(workflow_files);
	}
	
	predefined_pane.setLayout(new BorderLayout(5,0));
	predefined_pane.add(predefined_label, BorderLayout.LINE_START);
	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 ChangeDirListener implements ActionListener {
	public void actionPerformed(ActionEvent event) {
	    JFileChooser chooser = new JFileChooser(collect_dir_field.getText());
	    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
	    int returnVal = chooser.showOpenDialog(Preferences.this);
	    if(returnVal == JFileChooser.APPROVE_OPTION) {
		collect_dir_field.setText(chooser.getSelectedFile().getAbsolutePath() + File.separator);
	    } // else collect_dir_field text remains as it is
	}
    }

    private class OKButtonListener
	implements ActionListener {
	private boolean close;
	public OKButtonListener(boolean close) {
	    this.close = close;
	}

	private void setProxyHostForProtocol(String protocol,
					     JTextField proxy_host_field,
					     JSpinner proxy_port_field)
	{	    
	    Configuration.setString("general."+protocol+"_proxy_host", true, proxy_host_field.getText());
	    Configuration.setString("general."+protocol+"_proxy_port", true, proxy_port_field.getValue() + "");
	}
	
	public void actionPerformed(ActionEvent event)
	{
	    // Several options requiring restarting the GLI to apply: 
	    // interface font, interface language, changed gliserver url or library url
	    boolean restart_required = false;
	    boolean keep_collection_open = false;
	    String restart_message = "";

	    
	    // 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 old_library_url = (Configuration.library_url == null) ? null : Configuration.library_url.toString();
	    String library_url_string = library_path_field.getText();
	    if(old_library_url != null && !old_library_url.equals(library_url_string)) {

		// If the server is remote and the library path's been changed, then GLI client needs restart
		// If the server is local, GLI is going to work with the collection of GSDLPath anyway, 
		// even if the library path for previewing has changed
		if (Gatherer.isGsdlRemote) {
		    restart_required = true;
		    restart_message = Dictionary.get("Preferences.General.Manual_Restart_Required");
		    
		}
		if(Gatherer.c_man.getCollection() != null) {
		    // if the gliserver url has changed while a collection is open, 
		    // close the open collection of the old library URL
		    Gatherer.g_man.saveThenCloseCurrentCollection();
		    Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(), true, "");
		}
	    }
	    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"+Configuration.gliPropertyNameSuffix(), 
				    true, library_url_string);

	    if (Gatherer.isGsdlRemote && !Gatherer.GS3) {
		String old_gliserver_url = Configuration.gliserver_url.toString(); 
		String gliserver_url_string = gliserver_url_field.getText();
		if(!old_gliserver_url.equals(gliserver_url_string)) {
		    restart_required = true;
		    restart_message = Dictionary.get("Preferences.General.Manual_Restart_Required");

		    if(Gatherer.c_man.getCollection() != null) {
			// if the gliserver url has changed while a collection is open, 
			// close the open collection of the old gliserver URL
			Gatherer.g_man.saveThenCloseCurrentCollection();
			Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(), true, "");
		    }
		}
		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());
	    setProxyHostForProtocol(HTTP, http_proxy_host_field, http_proxy_port_field);
	    setProxyHostForProtocol(HTTPS, https_proxy_host_field, https_proxy_port_field);
	    setProxyHostForProtocol(FTP, ftp_proxy_host_field, ftp_proxy_port_field);
	    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());


	    // 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;
		restart_message = Dictionary.get("Preferences.General.Restart_Required");

	    }

	    // GLI interface language
	    String current_lang = Configuration.getLanguage();
	    if (!current_lang.equals(((DictionaryEntry) language_combobox.getSelectedItem()).getLocale().getLanguage())) {
	      // need to save the collection before changing the locale otherwise it stuffs the metadata names up
	      if(Gatherer.c_man.getCollection() != null) {
		  Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(), true, Gatherer.c_man.getLoadedCollectionColFilePath());
		  Gatherer.g_man.saveThenCloseCurrentCollection();
		  keep_collection_open = true;
		}

		Configuration.setLocale("general.locale", Configuration.GENERAL_SETTING, ((DictionaryEntry) language_combobox.getSelectedItem()).getLocale());
		restart_required = true;
		restart_message = Dictionary.get("Preferences.General.Restart_Required");
	    }

	    // Inform the user that a restart is required, if necessary
	    if (restart_required) {
		JOptionPane.showMessageDialog(Gatherer.g_man, restart_message, 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 (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 && !Gatherer.isGsdlRemote) {
		// shut down the collection
		System.err.println("shutting down the 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();
	    if (Gatherer.isGsdlRemote && Gatherer.GS3 && site_changed ){
		Gatherer.remoteGreenstoneServer.downloadCollectionConfigurations();
	    }
	    // Refresh the GLI to account for the configuration changes
	    Gatherer.refresh(Gatherer.PREFERENCES_CHANGED);

	    // If proxy is on but proxy details are incomplete, then can't continue 
	    if (use_proxy_checkbox.isSelected()
		&& http_proxy_host_field.getText().equals("")
		&& https_proxy_host_field.getText().equals("")
		&& ftp_proxy_host_field.getText().equals("")) {
		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Preferences.Connection.Proxy_Host_Missing"),
					      Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
	    } else {
		// Hide dialog
		if (close) {
		    self.dispose();
		}
	    }

		// collect directory change
	    String newCollectPath = collect_dir_field.getText();
	    if(!newCollectPath.endsWith(File.separator)) {
		newCollectPath += File.separator;
	    }
		// wait cursor will display while changing the collect directory, need to work out what component to
		// display it on: main GLI frame or Preferences window, depending on if OK or Apply was pressed
		Container container = close ? Gatherer.g_man.getContentPane() : Preferences.this.getContentPane();
	    Gatherer.collectDirectoryHasChanged(Gatherer.getCollectDirectoryPath(), 
				newCollectPath, container);
			// will tell the server that the collect directory has changed and that
			// the workspace needs to be refreshed (Documents in Greenstone Collections)	   
		
	    if (restart_required) {
	      if (keep_collection_open) {
		Gatherer.g_man.exitNoCollectionSave(Gatherer.EXIT_THEN_RESTART);
	      } else {
		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 {
		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"));
		workflow_files.setSelected(element.getEnabled("files"));
	    }
	}
    }


    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("The site changed to = "+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);
		}
		if (Gatherer.isGsdlRemote){
		    // Close the current collection, remove the lock on this file, ask to login to the new site, then download collection configurations of the site.
		    if (Gatherer.c_man.getCollection()!=null){
			// why doing this lock file by hand? closeCurrentCollection also deletes the lock file on the server.
			//File lock_file = new File(Gatherer.c_man.getLoadedCollectionDirectoryPath() + "gli.lck");
			//Gatherer.remoteGreenstoneServer.deleteCollectionFile(Gatherer.c_man.getLoadedCollectionName(),lock_file);
			Gatherer.g_man.closeCurrentCollection();
		    }
		    Configuration.site_name=site;
		    // kjdon - commented this out as we only have one set of
		    // users for entire gs install. And this will cause an authentication popup from inside PReferences which cannot display as its waiting for
		    // prefs to finish before running itself.
		    //Gatherer.remoteGreenstoneServer.set_remote_greenstone_server_authentication_to_null();
		    System.err.println("download colls");
		    Gatherer.remoteGreenstoneServer.downloadCollectionConfigurations();
		}
	    }
	}    
    }

    private class NoCheckCertificateListener implements ActionListener {
	public void actionPerformed(ActionEvent event) {
	    boolean isEnabled = no_check_certificate_checkbox.isSelected();
	    Configuration.set("general.no_check_certificate", true, isEnabled);
	    boolean no_check_cert_enabled = Configuration.get("general.no_check_certificate", 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.
	    http_proxy_host_field.setEnabled(enabled);
	    http_proxy_port_field.setEnabled(enabled);
	    https_proxy_host_field.setEnabled(enabled);
	    https_proxy_port_field.setEnabled(enabled);
	    ftp_proxy_host_field.setEnabled(enabled);
	    ftp_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;
	}
    }
}
