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

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import org.apache.xerces.parsers.*;
import org.greenstone.gatherer.Configuration;
import org.greenstone.gatherer.DebugStream;
import org.greenstone.gatherer.Gatherer;
import org.greenstone.gatherer.LocalLibraryServer;
import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
import org.greenstone.gatherer.util.Utility;
import org.w3c.dom.*;
import org.xml.sax.*;

/** This manager provides access to submanagers, which in turn provide tools for the designing of Greenstone collections via the information stored in etc/collect.cfg. This class acts as a hub for the managers that handle specific parts of the configuration such as classifiers, format strings and language settings.
 * @author John Thompson, Greenstone Digital Library, University of Waikato
 * @version 2.3d
 */
public class CollectionDesignManager {
    /** This listener listens for any event on any of the components in any of the sub-views, and marks the collection as needing saving if any change occurs. */
    static public CDMChangeListener change_listener;
    /** These listeners listen to changes in the Design mode so as to allow minimal rebuilding */
    static public DesignChangeListener all_change_listener;
    static public DesignChangeListener buildcol_change_listener;
    /** A list of classifiers to use at build time. */
    static public ClassifierManager classifier_manager;
    /** The CollectionConfiguration object on which this CDM will be based. */
    static public CollectionConfiguration collect_config;
    /** A manager of collection level metadata. */
    static public CollectionMetaManager collectionmeta_manager;
    /** A list of formating strings to use at build time. */
    static public FormatManager format_manager;
    /** A manager of general options */
    static public GeneralManager general_manager;
    /** List of indexes to be built, and the default index. 
     also handles build type and levels */
    static public IndexingManager index_manager;
    /** Contains instructions dealing with the collection language. */
    static public LanguageManager language_manager;
    /** Handling writing extra.dm file */
    static public MacrosManager macros_manager;
    /** A list of plugins to use at build time. */
    static public PluginManager plugin_manager;
    /** a manager of searching metadata such as index names*/ 
    static public SearchMetadataManager searchmetadata_manager;
    /** Contains: A list of subcollections, (defined on metadatadata), a list of which subcollection indexes to build and the default subcollection index. */
    static public SubcollectionManager subcollection_manager;

    static public SubcollectionIndexManager subcollectionindex_manager;
    /** A supercollection command allows a single search to be conducted across several collections. It is a very basic command and so avoids all the crazy model stuff that exists in most of the design managers. */
    static public SuperCollectionManager supercollection_manager; // Just cause I could ;p
    /** The text translation manager. */
    static public TranslationView translation_manager;
    /** These mark what needs to happen when building a collection where ONLY design options have been changed.
        The build requirements of the higher numbers must include doing everything from the lower numbers. */
    static final public int ALL = 3;
    static final public int BUILDCOL = 2;
    static final public int NOTHING = 0;
    static private int rebuildTypeRequired = NOTHING; //Rebuild type required if only design options have changed

    /** Constructor. Loads a certain collection configuration file, which is parsed into a DOM. This model is then registered with the command information managers, each of whom knows how to, and provides controls to, alter certain commands.
     * @param collect_config_file the File representing a collection configuration file either in its text (G2) or xml (G3) form
     */
    public CollectionDesignManager(File collect_config_file) {
	DebugStream.println("Initializaing CollectionDesignModule.");
	change_listener = new CDMChangeListener();
	all_change_listener = new DesignChangeListener(ALL);
	buildcol_change_listener = new DesignChangeListener(BUILDCOL);
	// Parse the collection configuration
	collect_config = new CollectionConfiguration(collect_config_file);
	if (DebugStream.isDebuggingEnabled()) {
	    collect_config.display();
	}
	loadDesignDetails();
	DebugStream.println("CollectionDesignModule loaded.");
    }

    /** Reloads the various managers to ensure they have built themselves from the latest details available in the collection configuration class
     * @see org.greenstone.gatherer.cdm.ClassifierManager
     * @see org.greenstone.gatherer.cdm.CollectionMetaManager
     * @see org.greenstone.gatherer.cdm.FormatManager
     * @see org.greenstone.gatherer.cdm.GeneralManager
     * @see org.greenstone.gatherer.cdm.IndexManager
     * @see org.greenstone.gatherer.cdm.LanguageManager
     * @see org.greenstone.gatherer.cdm.PluginManager
     * @see org.greenstone.gatherer.cdm.SubcollectionIndexManager
     * @see org.greenstone.gatherer.cdm.SubcollectionManager
     * @see org.greenstone.gatherer.cdm.SuperCollectionManager
     * @see org.greenstone.gatherer.cdm.TranslationView
     */
    private void loadDesignDetails() {
	// Create the command information managers, registering the config file with each as necessary
	language_manager = new LanguageManager(collect_config.getLanguages());
	collectionmeta_manager = new CollectionMetaManager();
	classifier_manager = new ClassifierManager();
	general_manager = new GeneralManager();
	macros_manager = new MacrosManager();
	index_manager = new IndexingManager();
	plugin_manager = new PluginManager();
	subcollection_manager = new SubcollectionManager();
	subcollectionindex_manager = new SubcollectionIndexManager(collect_config.getSubIndexes());
	supercollection_manager = new SuperCollectionManager(collect_config.getSuperCollection());
	searchmetadata_manager = new SearchMetadataManager();
	translation_manager = new TranslationView();
	format_manager = new FormatManager(); // Parse formats at the very end, given that they depend upon several other managers to appear properly.
    }

    /** This method deconstructs each of the managers, causing them to dispose of their controls.
     */
    public void destroy() {
	// Remove references from persistant listeners.
	classifier_manager.destroy();
	classifier_manager = null;
	searchmetadata_manager.destroy();
	searchmetadata_manager = null;
	format_manager.destroy();
	format_manager = null;
	general_manager.destroy();
	general_manager = null;
	index_manager.destroy();
	index_manager = null;
	language_manager.destroy();
	language_manager = null;
	plugin_manager.destroy();
	plugin_manager = null;
	subcollection_manager.destroy();
	subcollection_manager = null;
	supercollection_manager.destroy();
	supercollection_manager = null;
	translation_manager.destroy();
	translation_manager = null;
    }

    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
     * @param mode the new mode as an int
     */
    public void modeChanged(int mode) {
	plugin_manager.modeChanged(mode);
	classifier_manager.modeChanged(mode);
	subcollection_manager.modeChanged(mode);
	supercollection_manager.modeChanged(mode);
	format_manager.modeChanged(mode);
	index_manager.modeChanged(mode);
	translation_manager.modeChanged(mode);
	general_manager.modeChanged(mode);
	language_manager.modeChanged(mode);
	searchmetadata_manager.modeChanged(mode);
    }

    /** The cdm is considered to be ready if the collect.cfg file was found and parsed and the collection title is not error.
     * @return true if the collection is ready, false otherwise
     */
    public boolean ready() {
	return collect_config.ready();
    }


    /** Cause the current collection configuration to be written out to disk.
     */
    public void save()
    {
	collect_config.saveIfNecessary();
    }


    public static int getRebuildTypeRequired() {
	return rebuildTypeRequired;
    }
    public static void resetRebuildTypeRequired() {
	setRebuildTypeRequired(NOTHING);
    }
    public static void setRebuildTypeRequired(int number) {
	rebuildTypeRequired = number;
    }

    /**
     * What exactly does this do?
     */
    private class CDMChangeListener
	implements ActionListener, DocumentListener {

	/** Gives notification that an event has happened */
	public void actionPerformed(ActionEvent event) {
	    Gatherer.c_man.getCollection().setSaved(false);
	}

	/** Gives notification that an attribute or set of attributes changed. */
	public void changedUpdate(DocumentEvent e) {
	    Gatherer.c_man.getCollection().setSaved(false);
	}

	/** Gives notification that there was an insert into the document. */
	public void insertUpdate(DocumentEvent e) {
	    Gatherer.c_man.getCollection().setSaved(false);
	}

	/** Gives notification that a portion of the document has been removed. */
	public void removeUpdate(DocumentEvent e) {
	    Gatherer.c_man.getCollection().setSaved(false);
	}
    }
}
