package org.greenstone.gatherer.collection;


import java.io.*;
import org.greenstone.gatherer.DebugStream;
import org.greenstone.gatherer.Gatherer;
import org.greenstone.gatherer.cdm.Argument;
import org.greenstone.gatherer.cdm.Classifier;
import org.greenstone.gatherer.cdm.CollectionDesignManager;
import org.greenstone.gatherer.metadata.MetadataElement;
import org.greenstone.gatherer.metadata.MetadataTools;
import org.greenstone.gatherer.metadata.ProfileXMLFileManager;
import org.greenstone.gatherer.util.StaticStrings;
import org.greenstone.gatherer.util.Utility;


/**
 * Importing legacy collections involves two main steps:
 *
 * 1. Read the existing metadata.xml files and namespace them, usually by prompting the user
 *    to specify the mapping between old metadata elements and new elements.
 *
 * 2. Fix up the classify commands in the collect.cfg file to specify the new element names.
 *
 * @author Michael Dewsnip
 */
public class LegacyCollectionImporter 
{
    /** Definition of an important directory name, in this case the backup import directory for the collection. */
    static final public String IMPORT_BAK_DIR = "import.bak" + File.separator;


    // This copies all the existing metadata.xml files into a backup directory
    static public void backupMetadataXMLFiles(File collection_dir)
    {
	File import_dir = new File(collection_dir, "import");
	File import_bak_dir = new File(collection_dir, IMPORT_BAK_DIR);
	import_bak_dir.mkdir();
	copyMetadataXMLFiles(import_dir, import_bak_dir);
    }


    static private void copyMetadataXMLFiles(File source_dir, File backup_dir)
    {
	if (source_dir == null || !source_dir.exists()) {
	    return;
	}

	// Find the metadata file in this dir
	File metadata_xml_file_file = new File(source_dir, "metadata.xml");
	if (metadata_xml_file_file.exists()) {
	    File new_metadata_xml_file_file = new File(backup_dir, "metadata.xml");
	    try {
		backup_dir.mkdirs();
		Gatherer.f_man.getQueue().copyFile(metadata_xml_file_file, new_metadata_xml_file_file, false);
		if (!new_metadata_xml_file_file.exists()) {
		    throw new Exception("");
		}
	    }
	    catch (Exception e) {
		DebugStream.println("Exception: couldn't copy the file " + metadata_xml_file_file.getPath() + e.getMessage());
	    }
	}

	// Now go through child directories
	File [] children = source_dir.listFiles();
	for (int i = 0; i < children.length; i++) {
	    File child = children[i];
	    if (child.isDirectory()) {
		copyMetadataXMLFiles(child, new File(backup_dir, child.getName()));
	    }
	}
    }


    static public void updateClassifiers(CollectionDesignManager cdm)
    {
	// Update the metadata elements in each of the classifiers
	for (int i = 0; i < cdm.classifier_manager.getSize(); i++) {
	    Classifier classifier = cdm.classifier_manager.getClassifier(i);
	    // System.err.println("Classifier: " + classifier);

	    // Update the "-metadata" value
	    Argument metadata_argument = classifier.getArgument("-metadata");
	    String metadata_argument_value = metadata_argument.getValue();
	    String metadata_element_name_full = mapLegacyMetadataElementName(metadata_argument_value);
	    if (metadata_element_name_full != null && !metadata_element_name_full.equals("")) {
		String metadata_element_display_name_full = MetadataTools.getDisplayNameForMetadataElementWithName(metadata_element_name_full);
		if (metadata_element_display_name_full != null) {
		    metadata_argument_value = metadata_element_display_name_full;
		    metadata_argument.setValue(metadata_argument_value);
		}
	    }

  	    // Update the "-sort" value
	    Argument sort_argument = classifier.getArgument("-sort");
	    if (sort_argument != null) {
		String sort_element_name_full = mapLegacyMetadataElementName(sort_argument.getValue());
		if (sort_element_name_full != null && !sort_element_name_full.equals("")) {
		    String sort_element_display_name_full = MetadataTools.getDisplayNameForMetadataElementWithName(sort_element_name_full);
		    if (sort_element_display_name_full != null) {
			sort_argument.setValue(sort_element_display_name_full);
		    }
		}
	    }

	    // Set the "-buttonname" value if it isn't already set
	    Argument buttonname_argument = classifier.getArgument("-buttonname");
	    if (buttonname_argument != null && buttonname_argument.getValue().equals("")) {
		int namespace_index = metadata_argument_value.indexOf(".");
		if (namespace_index != -1) {
		    buttonname_argument.setValue(metadata_argument_value.substring(namespace_index + 1));
		}
		else {
		    buttonname_argument.setValue(metadata_argument_value);
		}
		buttonname_argument.setAssigned(true);
	    }

	    // With Hierarchy classifiers, update the hfile arguments
  	    if (classifier.getName().equalsIgnoreCase(StaticStrings.HIERARCHY_CLASSIFIER)) {
		// Update the "-hfile" value
		Argument hfile_argument = classifier.getArgument(StaticStrings.HFILE_ARGUMENT);
		hfile_argument.setValue(metadata_element_name_full + ".txt");
  	    }

	    // System.err.println("Classifier (after): " + classifier);
	}
    }


    static private String mapLegacyMetadataElementName(String metadata_element_name)
    {
 	// Remove the extracted namespace if it has been added, but only
	// if there are no subsequent namespaces following it (like ex.dc.*)
	// since we want to preserve embedded metadata names as is.
 	if (metadata_element_name.startsWith(StaticStrings.EXTRACTED_NAMESPACE) && metadata_element_name.indexOf(StaticStrings.NS_SEP, StaticStrings.EXTRACTED_NAMESPACE.length()) == -1) {
 	    metadata_element_name = metadata_element_name.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
 	}

 	// Update the metadata value to the new (namespaced) one
	return ProfileXMLFileManager.getMetadataElementFor(metadata_element_name);
    }
}
