/**
 *#########################################################################
 *
 * 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.event.*;
import java.io.*;
import javax.swing.event.*;
import org.greenstone.gatherer.DebugStream;
import org.greenstone.gatherer.Gatherer;
import org.greenstone.gatherer.collection.CollectionManager;
import org.w3c.dom.*;

//save()
import org.greenstone.gatherer.util.XMLTools;
import javax.swing.*;

/** 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;
    static public DesignChangeListener databasecol_change_listener;

    /** The CollectionConfiguration object on which this CDM will be based. */
    static public CollectionConfiguration collect_config;
  
  /** The managers for different parts of the collection configuration file */
    /** A list of classifiers to use at build time. */
    static public ClassifierManager classifier_manager;
    /** A manager of collection level metadata. */
    static public CollectionMetaManager collectionmeta_manager;
    /** A manager of configuring depositor metadata */ 
    static public DepositorMetadataManager depositormetadata_manager;
    /** A list of formating strings to use at build time. */
    static public SharedByTwoFormatManager 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 searchmeta_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

    /** This indicates whether a minimal or complete build is required.
        Minimal means do an incremental rebuild. Complete means do a full rebuild
        Note: This stores preceisely whether the user selected the minimal or full build radio button.
        Its value does not indicate anything about what gli eventually chose as a result of that "suggestion" */
    static private boolean isCompleteBuild = false;

    /** These remember which scripts were run for the last build.
        true indicated 'full-' prefix, false indicates 'incremental-' prefix to the given perl script (import.pl or buildcol.pl)
        Note: This stores what gli did, regardless of whether minimal or full was requested by the user */
    static private boolean importWasFull = false;
    static private boolean buildcolWasFull = false;

    /** 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);
	databasecol_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.");
    }


    public void reloadConfig() {
	// Parse and load the current collection configuration again
	// Used after GLI > Edit > collectionConfig.xml > Save to get these edits into GLI.
	
	collect_config.reload();
	if (DebugStream.isDebuggingEnabled()) {
	    collect_config.display();
	}
        destroy();// remove old managers and unhook the listeners
	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.Format4gs3Manager
     * @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
     * @see org.greenstone.gatherer.cdm.DepositorMetadataManager
     */
    private void loadDesignDetails() {
	// Create the command information managers, registering the config file with each as necessary
	
	classifier_manager = new ClassifierManager();
	collectionmeta_manager = new CollectionMetaManager();
        depositormetadata_manager = new DepositorMetadataManager();
        if (Gatherer.GS3) {
          format_manager = new Format4gs3Manager();
	} else {
          format_manager = new FormatManager(); // Parse formats at the very end, given that they depend upon several other managers to appear properly.
	}
	general_manager = new GeneralManager();	
	index_manager = new IndexingManager();
        language_manager = new LanguageManager(collect_config.getLanguages());
        macros_manager = new MacrosManager();
	plugin_manager = new PluginManager();
        searchmeta_manager = new SearchMetadataManager();
	subcollection_manager = new SubcollectionManager();
	subcollectionindex_manager = new SubcollectionIndexManager(collect_config.getSubIndexes());
	supercollection_manager = new SuperCollectionManager(collect_config.getSuperCollection());
 	translation_manager = new TranslationView();

    }

    /** 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;
        collectionmeta_manager.destroy();
        collectionmeta_manager = null;
	depositormetadata_manager.destroy();
	depositormetadata_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;
        macros_manager.destroy();
        macros_manager = null;
	plugin_manager.destroy();
	plugin_manager = null;
	searchmeta_manager.destroy();
	searchmeta_manager = null;
	subcollection_manager.destroy();
	subcollection_manager = null;
        subcollectionindex_manager.destroy();
        subcollectionindex_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) {
	if(classifier_manager != null) classifier_manager.modeChanged(mode);
        if (collectionmeta_manager != null) collectionmeta_manager.modeChanged(mode);
	if(depositormetadata_manager != null) depositormetadata_manager.modeChanged(mode);
        //if(format_manager != null) format_manager.modeChanged(mode);
        if(general_manager != null) general_manager.modeChanged(mode);
        if(index_manager != null) index_manager.modeChanged(mode);
        if(language_manager != null) language_manager.modeChanged(mode);
        if (macros_manager != null) macros_manager.modeChanged(mode);
        if (plugin_manager != null) plugin_manager.modeChanged(mode);	
	if(searchmeta_manager != null) searchmeta_manager.modeChanged(mode);
        if(subcollection_manager != null) subcollection_manager.modeChanged(mode);
        if(subcollectionindex_manager != null) subcollectionindex_manager.modeChanged(mode);
	if(supercollection_manager != null) supercollection_manager.modeChanged(mode);
        if(translation_manager != null) translation_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;
    }

    public static boolean isCompleteBuild() {
        return isCompleteBuild;
    }
    public static void setCompleteBuild(boolean icb) {
        isCompleteBuild = icb;
    }

	public static void setImportWasFull( boolean wasFull ) {
		importWasFull = wasFull;
	}
	public static boolean importWasFull() {
		return importWasFull;
	}
	public static void setBuildcolWasFull( boolean wasFull ) {
		buildcolWasFull = wasFull;
	}
	public static boolean buildcolWasFull() {
		return buildcolWasFull;
	}

    /**
     * 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);
	}
    }
}
