//------------------------------------------------------------------------------
// 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.Collection;
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.common.util.URI;
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.diagram.ui.service.DiagramImageService;
import org.eclipse.epf.export.services.DiagramHandler;
import org.eclipse.epf.export.xml.ExportXMLPlugin;
import org.eclipse.epf.export.xml.ExportXMLResources;
import org.eclipse.epf.library.IConfigurationManager;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.util.ModelStructure;
import org.eclipse.epf.library.edit.util.Suppression;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.layout.ElementLayoutManager;
import org.eclipse.epf.library.services.SafeUpdateController;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.library.util.MigrationUtil;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.uma.Activity;
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 boolean debug = ExportXMLPlugin.getDefault().isDebugging();

	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()
							.getCurrentMethodLibraryLocation()), new File(data
							.getXMLFile()).getParentFile());
			ContentProcessor contentProc = new ContentProcessor(handler,
					this.logger);
			
			diagramHandler = new DiagramHandler(
					new File(LibraryService.getInstance()
							.getCurrentMethodLibraryLocation()), new File(data
							.getXMLFile()).getParentFile()) {
				
				public void visitElementMap(int passId) {
					if (passId != 0) {
						return;
					}
/*					String libFolderPath = getSourceLibRoot().getAbsolutePath();
					int ix = libFolderPath.length();*/
					
					Map<String, MapEntryValue> map = getElementMap();
					for (Iterator<MapEntryValue> it = map.values().iterator(); it.hasNext(); ) {
						MapEntryValue value = it.next();
						if (value.targetFile == null) {
							continue;
						} else if (value.sourceFile != null) {
							EDataObject xmlObj = getXmlObject(value.element);
							if (xmlObj instanceof org.eclipse.epf.xml.uma.Process) {
								org.eclipse.epf.xml.uma.Process proc = 
													(org.eclipse.epf.xml.uma.Process) xmlObj;
								String uri = value.sourceFile.getAbsolutePath();
								String srcRootFolderPath = getRoot(value.element).getAbsolutePath();
								int ix = srcRootFolderPath.length();
								
								uri = uri.substring(ix + 1);
								uri = URI.createFileURI(uri).toString();
								proc.setDiagramURI(uri);
							}		
						} 
					}	
				}
				
				public void execute() {
					super.execute();
					SafeUpdateController.syncExec(new Runnable() {
						public void run() {
							exportDiagramImageFiles();
						}
					});
				}

				private void exportDiagramImageFiles() {
					String folderPath = LibraryService.getInstance().getCurrentMethodLibraryLocation();
					
					DiagramImageService diagramService = new DiagramImageService(null);
					diagramService.setForXMLExport(true);
					
					try {
						Map<String, MapEntryValue> map = getElementMap();
						for (Iterator<MapEntryValue> it = map.values().iterator(); it.hasNext(); ) {
							MapEntryValue value = it.next();
							org.eclipse.epf.uma.Process proc = (org.eclipse.epf.uma.Process) value.element;
							MethodConfiguration config = proc.getDefaultContext();
							if (config == null) {
								continue;
							}
							diagramService.setConfig(config);
							IConfigurationManager mgr = LibraryService.getInstance().getConfigurationManager(config);
							if (mgr == null) {
								continue;
							}
							ElementLayoutManager layoutMgr = mgr.getElementLayoutManager();
							if (layoutMgr == null) {
								continue;
							}
							IFilter filter = layoutMgr.getDiagramAdapterFactory().getFilter();
							
							File diagramXmiFile = value.targetFile;
							if (diagramXmiFile == null || !diagramXmiFile.exists()) {
								continue;
							}
							diagramService.setPubDir(diagramXmiFile.getParentFile());
							
							Map activities = MigrationUtil.getActivities(proc, true);	
							for (Activity act: (Collection<Activity>) activities.values()) {
								String[] types = {	ResourceHelper.DIAGRAM_TYPE_WORKFLOW,
													ResourceHelper.DIAGRAM_TYPE_ACTIVITY_DETAIL,
													ResourceHelper.DIAGRAM_TYPE_WP_DEPENDENCY};
								
								for (int i = 0; i < types.length; i++) {
									String imagePath = ResourceHelper.getXmlExportedDiagramImageFileName(act, types[i], ResourceHelper.FILE_EXT_JPEG);
									try {
										diagramService.saveDiagram(act, imagePath, types[i], filter, Suppression.getSuppression(proc));
									} catch (Exception e) {
										if (debug) {
											logger.logError(NLS.bind(ExportXMLResources.exportXMLService_error,
													e.getMessage()), e);
										}
									}
								}
							}
						}
						
					} catch (Exception e) {
						if (debug) {
							logger.logError(NLS.bind(ExportXMLResources.exportXMLService_error,
									e.getMessage()), e);
						}
					} finally {										
						diagramService.dispose();
					}
				}
			};

			// 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);
			
			diagramHandler.visitElementMap(0);
			if (data.exportType == ExportXMLData.EXPORT_METHOD_PLUGINS) {
				xmlLib.storeExtraInfo(src.getMethodPlugins());
			}
			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();) {
				Object nextObj = it.next();
				MethodElement child = nextObj instanceof MethodElement ?
						(MethodElement) nextObj : null;
				if (child == null) {
					continue;
				}

				// 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 && ! feature.getName().equals("methodElementProperty")) {//$NON-NLS-1$	
					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);
	//		
	// }
}
