//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.export.xml.services;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.sdo.EDataObject;
import org.eclipse.epf.dataexchange.util.ContentProcessor;
import org.eclipse.epf.dataexchange.util.IResourceHandler;
import org.eclipse.epf.export.services.DiagramHandler;
import org.eclipse.epf.export.xml.ExportXMLResources;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.edit.util.ModelStructure;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.uma.Diagram;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.WorkOrder;
import org.eclipse.epf.uma.WorkOrderType;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.osgi.util.NLS;

/**
 * XmlExport service class to process the exporting task
 * 
 * @author Jinhua Xi
 * @since 1.0
 */
public class ExportXMLService {

	// String xmlPath;
	private ExportXMLData data;

	private XMLLibrary xmlLib;

	private List discardedElements = new ArrayList();

	ExportXMLLogger logger = null;

	// in case we need to mapping the uma objects to xml objects
	// such as the content categories
	private Map umaIdToXmlIdMap = new HashMap();
	
	private DiagramHandler diagramHandler;
	
	//tds with steps
	private Map<String, TaskDescriptor> tdMap;

	/**
	 * Creates a new instance.
	 */
	public ExportXMLService(ExportXMLData data) {
		this.data = data;
		logger = new ExportXMLLogger(new File(this.data.xmlFile)
				.getParentFile());
	}
	/**
	 * Gets the logger file.
	 */
	public File getLogPath() {
		return logger.getLogPath();
	}

	/**
	 * Dispose
	 */
	public void dispose() {
		logger.dispose();
	}

	/**
	 * Does XML library export.
	 */
	public void doExport(IProgressMonitor monitor) {
		try {

			IResourceHandler handler = new ExportResourceHandler(
					new File(LibraryService.getInstance()
							.getCurrentMethodLibraryPath()), new File(data
							.getXMLFile()).getParentFile());
			ContentProcessor contentProc = new ContentProcessor(handler,
					this.logger);
			
			diagramHandler = new DiagramHandler(
					new File(LibraryService.getInstance()
							.getCurrentMethodLibraryPath()), new File(data
							.getXMLFile()).getParentFile());

			// FeatureManager.INSTANCE.printFeatureNameMapping();

			// export the current library to the xml file
			// get the current library instance and export all to the xml
			MethodLibrary src = LibraryService.getInstance()
					.getCurrentMethodLibrary();

			this.xmlLib = new XMLLibrary(contentProc, logger, data
					.getXMLFile());

			this.xmlLib.createLibrary(src.getGuid(), src.getName());
			EDataObject target = this.xmlLib.getRoot();

			creatEDataObjectTree(src, target);
			iteratEDataObject(src);

			this.xmlLib.fixLibraryForExport();
			this.xmlLib.fixTaskDescriptorsForExport(tdMap);
			
			this.xmlLib.save();
			diagramHandler.execute();

		} catch (Exception e) {
			logger.logError(NLS.bind(ExportXMLResources.exportXMLService_error,
					e.getMessage()), e);
		}
	}

	private boolean isPluginSelected(MethodPlugin plugin) {
		if (data.exportType == ExportXMLData.EXPORT_METHOD_LIBRARY) {
			return true;
		} else if (data.exportType == ExportXMLData.EXPORT_METHOD_PLUGINS) {
			return (data.selectedPlugins != null)
					&& data.selectedPlugins.contains(plugin);
		} else if (data.exportType == ExportXMLData.EXPORT_METHOD_CONFIGS) {
			return false;
		} else {
			return true;
		}
	}

	private boolean isConfigExcluded(MethodConfiguration config) {
		if (data.exportType == ExportXMLData.EXPORT_METHOD_PLUGINS) {
			return data.associatedConfigs == null || 
					!data.associatedConfigs.contains(config.getGuid());
		} 
		return false;
	}
	
	private void creatEDataObjectTree(MethodElement srcObj,
			EDataObject targetObj) {

		// if it's a plugin, skip all the system packages
		// and find the top most user packages
		if (srcObj instanceof MethodPlugin) {

			MethodPlugin plugin = (MethodPlugin) srcObj;
			if (!isPluginSelected(plugin)) {
				return;
			}

			// all system packages are discarded
			discardedElements.addAll(TngUtil.getAllSystemPackages(plugin));

			List topmostUserPackages = getTopmostUserPackage(plugin);
			List categoryPkgs = TngUtil.getContentCategoryPackages(plugin);

			org.eclipse.epf.xml.uma.ContentCategoryPackage xmlPkg = (org.eclipse.epf.xml.uma.ContentCategoryPackage) this.xmlLib
					.getContentCategoryPackage(plugin.getGuid());
			String contentCategoryPackageId = xmlPkg.getId();

			for (Iterator itp = topmostUserPackages.iterator(); itp.hasNext();) {
				MethodPackage pkg = (MethodPackage) itp.next();

				// if it's a category package,
				// create all contained elements in the single custom category
				// package
				if (categoryPkgs.contains(pkg)) {

					// set the it mapping
					setIdMapping(pkg.getGuid(), contentCategoryPackageId);
					creatEDataObjectTree(pkg, xmlPkg);
				} else {
					creatEDataObjectTree(pkg, targetObj);
				}
			}
		} else {
			for (Iterator it = srcObj.eContents().iterator(); it.hasNext();) {
				MethodElement child = (MethodElement) it.next();

				// in uma model, WorkOrder is contained in package
				// in xml model, WorkOrder is contained by the owning
				// WorkBreakdownElement,
				// so delay the creation if the owner is a package
				if (child instanceof WorkOrder
						&& srcObj instanceof MethodPackage) {
					continue;
				}

				if ((child instanceof MethodPlugin)
						&& !isPluginSelected((MethodPlugin) child)) {
					continue;
				}
				
				if (child instanceof MethodConfiguration &&
					isConfigExcluded((MethodConfiguration) child)) {
					continue;
				}

				if (!isDiscarded(child)) {
					createXmlObject(child, targetObj);
				}
			}
		}
	}

	private void setIdMapping(String umaId, String xmlId) {
		if (!umaIdToXmlIdMap.containsKey(umaId)) {
			umaIdToXmlIdMap.put(umaId, xmlId);
		}
	}

	private String getXmlId(String umaId) {
		if (umaIdToXmlIdMap.containsKey(umaId)) {
			return (String) umaIdToXmlIdMap.get(umaId);
		}
		return umaId;
	}

	private boolean isDiscarded(Object o) {
		if (o instanceof Diagram) {
			return true;
		}
		return discardedElements.contains(o);
	}

	private EDataObject getXmlObject(MethodElement srcObj) {
		String id = srcObj.getGuid();
		if (umaIdToXmlIdMap.containsKey(id)) {
			id = (String) umaIdToXmlIdMap.get(id);
		}
		return this.xmlLib.getElement(id);
	}

	/**
	 * create an xml element for the container, based on the uma element
	 * 
	 * @param umaElement
	 * @param targetContainer
	 */
	private void createXmlObject(MethodElement umaElement,
			EDataObject targetContainer) {
		EStructuralFeature feature = umaElement.eContainmentFeature();
		createXmlObject(umaElement, targetContainer, feature.getName());
	}

	/**
	 * create an xml element for the container, based on the uma element
	 * 
	 * @param umaElement
	 * @param targetContainer
	 */
	private void createXmlObject(MethodElement umaElement,
			EDataObject targetContainer, String containmentFeature) {

		try {
			if (umaElement == null) {
				return;
			}

			// get the containment feature so we can create the object of the
			// same type
			String elementType = umaElement.getType().getName();
			EDataObject xmlElement = xmlLib.createElement(targetContainer,
					containmentFeature, umaElement.eClass().getName(),
					elementType, umaElement.getGuid());
			
			if (umaElement instanceof TaskDescriptor) {					
				TaskDescriptor td = (TaskDescriptor) umaElement;
				if (td.getTask() != null) {
					List steps = td.getSelectedSteps();
					if (steps != null && !steps.isEmpty()) {
						if (tdMap == null) {
							tdMap = new HashMap<String, TaskDescriptor>();
						}
						tdMap.put(td.getGuid(), td);
					}
				}			
			}
			
			if (xmlElement != null) {

				// recursive
				creatEDataObjectTree(umaElement, xmlElement);
			}

		} catch (Exception e) {
			// log the error and continue???
			e.printStackTrace();
		}
	}

	private void iteratEDataObject(MethodElement srcObj) {
		diagramHandler.registerElement(srcObj, true);
		
		if (srcObj instanceof MethodPlugin) {
			MethodPlugin plugin = (MethodPlugin) srcObj;
			if (!isPluginSelected(plugin)) {
				return;
			}
		}

		if (isProcessed(srcObj.getGuid())) {
			return;
		}
		setProcessed(srcObj.getGuid());

		EDataObject targetObj = getXmlObject(srcObj);

		// if object is not created,
		// which means it's either a system package or something wrong
		if (targetObj == null) {
			if (srcObj instanceof MethodPackage) {
				// iterate the child packages
				for (Iterator it = ((MethodPackage) srcObj).getChildPackages()
						.iterator(); it.hasNext();) {
					iteratEDataObject((MethodElement) it.next());
				}
			}

			// // elements can be reference in other plugins
			// // don't need to care about this
			// else if (!isDiscarded(srcObj) ) {
			// logger.logWarning("Warning: xml object not created for " +
			// LibraryUtil.getTypeName(srcObj) );
			// }

			return;
		}

		EClass eClass = srcObj.eClass();

		EList features = eClass.getEAllStructuralFeatures();
		for (Iterator it = features.iterator(); it.hasNext();) {
			EStructuralFeature feature = (EStructuralFeature) it.next();

			Object value = srcObj.eGet(feature);

			try {
				if (value instanceof List) {
					for (Iterator itv = ((List) value).iterator(); itv
							.hasNext();) {
						MethodElement src_value = (MethodElement) itv.next();

						// handle the
						// UmaPackage#getWorkBreakdownElement_LinkToPredecessor
						// feature value
						// the WorkOrder in uma is a process element in a
						// package
						// in xml model, it's an EDataObject contained by the
						// WorkBreakdownElement
						if (src_value instanceof WorkOrder) {
							// get the owner of the WorkOrder
							EDataObject workOrder = getXmlObject(src_value);
							if (workOrder == null) {
								createXmlObject(src_value, targetObj, feature
										.getName());
							}
							// System.out.println("workorder value");
						}

						// set the reference
						String xmlId = getXmlId(src_value.getGuid());
						xmlLib.setReferenceValue(targetObj, feature.getName(),
								xmlId, src_value.getType());

						iteratEDataObject(src_value);
					}
				} else if (value instanceof MethodElement) {
					// get the xml object and iterate again
					MethodElement src_value = (MethodElement) value;

					// if ( src_value instanceof WorkOrder ) {
					// System.out.println("workorder value");
					// }

					// elements like Presentation may not have a Content
					// Description
					// the one returned may not have a container
					if (src_value.eContainer() != null) {
						String xmlId = getXmlId(src_value.getGuid());
						xmlLib.setReferenceValue(targetObj, feature.getName(),
								xmlId, src_value.getType());

						iteratEDataObject(src_value);
					}
				} else if (!isDiscarded(srcObj)) {
					// if ( targetObj instanceof ContentCategoryPackage) {
					// System.out.println("hrre");
					// }

					if (value instanceof WorkOrderType) {
						value = ((WorkOrderType) value).getName();
					}

					xmlLib.setAtributeFeatureValue(targetObj,
							feature.getName(), value);
				}
			} catch (Exception e) {
				String msg = NLS.bind(
						ExportXMLResources.exportXMLService_feature_error,
						LibraryUtil.getTypeName(srcObj), feature.getName());
				logger.logError(msg, e);
			}

		}

	}

	// goid of processed element
	private List processedElements = new ArrayList();

	private boolean isProcessed(String guid) {
		return processedElements.contains(guid);
	}

	private void setProcessed(String guid) {
		if (!processedElements.contains(guid)) {
			processedElements.add(guid);
		}
	}

	private List getTopmostUserPackage(MethodPlugin plugin) {

		MethodPackage pkg_core_content = UmaUtil.findMethodPackage(plugin,
				ModelStructure.DEFAULT.coreContentPath);

		MethodPackage pkg_custom_categories = UmaUtil.findMethodPackage(plugin,
				ModelStructure.DEFAULT.customCategoryPath);

		MethodPackage pkg_disciplines = UmaUtil.findMethodPackage(plugin,
				ModelStructure.DEFAULT.disciplineDefinitionPath);

		MethodPackage pkg_domains = UmaUtil.findMethodPackage(plugin,
				ModelStructure.DEFAULT.domainPath);

		MethodPackage pkg_rolesets = UmaUtil.findMethodPackage(plugin,
				ModelStructure.DEFAULT.roleSetPath);

		MethodPackage pkg_tools = UmaUtil.findMethodPackage(plugin,
				ModelStructure.DEFAULT.toolPath);

		MethodPackage pkg_wptypes = UmaUtil.findMethodPackage(plugin,
				ModelStructure.DEFAULT.workProductTypePath);

		MethodPackage pkg_cp = UmaUtil.findMethodPackage(plugin,
				ModelStructure.DEFAULT.capabilityPatternPath);

		MethodPackage pkg_dp = UmaUtil.findMethodPackage(plugin,
				ModelStructure.DEFAULT.deliveryProcessPath);

		MethodPackage pkg_proc_contribution = UmaUtil.findMethodPackage(plugin,
				ModelStructure.DEFAULT.processContributionPath);

		List pkgs = new ArrayList();
		pkgs.add(pkg_core_content);
		pkgs.add(pkg_custom_categories);
		pkgs.add(pkg_disciplines);
		pkgs.add(pkg_domains);
		pkgs.add(pkg_rolesets);
		pkgs.add(pkg_tools);
		pkgs.add(pkg_wptypes);
		pkgs.add(pkg_cp);
		pkgs.add(pkg_dp);

		if ( pkg_proc_contribution != null ) {
			pkgs.add(pkg_proc_contribution);
		}
		
		return pkgs;

		// List systemPkgs = TngUtil.getAllSystemPackages(plugin);
		//		
		// List unprocessedPkgs = new ArrayList(plugin.getMethodPackages());
		// while (unprocessedPkgs.size() > 0 ) {
		// MethodPackage pkg = (MethodPackage) unprocessedPkgs.remove(0);
		// if ( !systemPkgs.contains(pkg) ) {
		// if ( !pkgs.contains(pkg) ) {
		// pkgs.add(pkg);
		// }
		// continue;
		// }
		//			
		// for ( Iterator it = pkg.getChildPackages().iterator(); it.hasNext();
		// ) {
		// MethodPackage p = (MethodPackage)it.next();
		// if ( systemPkgs.contains(p) )
		// {
		// if ( !unprocessedPkgs.contains(p) ) {
		// unprocessedPkgs.add(p);
		// }
		// } else {
		// if ( !pkgs.contains(p) ) {
		// pkgs.add(p);
		// }
		// }
		// }
		//			
		// if ( unprocessedPkgs.size() == 0 ) {
		// break;
		// }
		// }
		//		
		// // need to include the content packages
		// pkgs.addAll(TngUtil.getContentCategoryPackages(plugin));

	}

	// private boolean isSystemPackage(EDataObject element) {
	//		
	// if ( !(element instanceof MethodPackage) ) {
	// return false;
	// }
	//		
	// MethodPlugin plugin = LibraryUtil.getMethodPlugin(element);
	// if ( plugin == null ) {
	// return false;
	// }
	//		
	// return TngUtil.getAllSystemPackages(plugin).contains(element);
	//		
	// }
}
