//------------------------------------------------------------------------------
// 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.importing.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.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.sdo.EDataObject;
import org.eclipse.epf.common.serviceability.MsgBox;
import org.eclipse.epf.common.serviceability.MsgDialog;
import org.eclipse.epf.common.serviceability.VersionUtil;
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.services.FeatureManager;
import org.eclipse.epf.export.xml.services.XMLLibrary;
import org.eclipse.epf.importing.ImportResources;
import org.eclipse.epf.importing.services.ConfigurationImportService;
import org.eclipse.epf.importing.services.FileModifyChecker;
import org.eclipse.epf.importing.services.LibraryImportManager;
import org.eclipse.epf.importing.wizards.PluginModifyInfo;
import org.eclipse.epf.importing.wizards.SelectImportConfigurationSource;
import org.eclipse.epf.importing.xml.ImportXMLPlugin;
import org.eclipse.epf.importing.xml.ImportXMLResources;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.services.SafeUpdateController;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.persistence.refresh.RefreshJob;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.xml.uma.Activity;
import org.eclipse.epf.xml.uma.CapabilityPattern;
import org.eclipse.epf.xml.uma.ContentCategory;
import org.eclipse.epf.xml.uma.ContentCategoryPackage;
import org.eclipse.epf.xml.uma.ContentPackage;
import org.eclipse.epf.xml.uma.DeliveryProcess;
import org.eclipse.epf.xml.uma.Discipline;
import org.eclipse.epf.xml.uma.Domain;
import org.eclipse.epf.xml.uma.Guidance;
import org.eclipse.epf.xml.uma.MethodElement;
import org.eclipse.epf.xml.uma.MethodLibrary;
import org.eclipse.epf.xml.uma.MethodPackage;
import org.eclipse.epf.xml.uma.MethodPlugin;
import org.eclipse.epf.xml.uma.ProcessComponent;
import org.eclipse.epf.xml.uma.ProcessPackage;
import org.eclipse.epf.xml.uma.UmaPackage;
import org.eclipse.epf.xml.uma.WorkOrder;
import org.eclipse.epf.xml.uma.WorkOrderType;
import org.eclipse.osgi.util.NLS;

/**
 * Xml import service class to process the importing task
 * 
 * @author Jinhua Xi
 * @since 1.0
 */
public class ImportXMLService {

	private boolean error = false;
	
	private Map renameElementMap = new HashMap();
	
	private boolean overwrite = false;
	
	private IStatus fileCheckedOutStatus = null;
	
	private String xmlPath;

	private XMLLibrary xmlLib;

	private UmaLibrary umaLib;

	private ImportXMLogger logger = new ImportXMLogger();

	private List discardedElements = new ArrayList();

	private DiagramHandler diagramHandler;
	
	// map xml WorkOrder to uma WorkOrder
	Map workOrderMap = new HashMap();

	/**
	 * The constructor
	 */
	public ImportXMLService() {

	}

	/**
	 * Loads the xml file.
	 * @param xmlPath
	 * @return true if succeeds.
	 */
	public boolean loadXml(final String xmlPath) {
		String versionError = versionCheck(xmlPath,	ImportXMLResources.importXMLWizard_title);		
		if (versionError != null) {
			return false;
		}
				
		this.xmlPath = xmlPath;

		logger.logMessage("Loading xml library ..."); //$NON-NLS-1$
		this.xmlLib = new XMLLibrary(null, logger, xmlPath);
		this.xmlLib.load();
		
		return checkOldPlugins();
	}
	
	private boolean checkOldPlugins() {
		List plugins = ((MethodLibrary) xmlLib.getRoot()).getMethodPlugin();
		List guids = new ArrayList();
		for (int i=0; i<plugins.size(); i++) {
			MethodElement elem = (MethodElement) plugins.get(i);
			guids.add(elem.getId());
		}				
		
		final PluginModifyInfo modifyInfo = SelectImportConfigurationSource
										.checkModify(guids, MsgBox.getDefaultShell(), false);		

		// allow user to proceed with locked plugins
		if ( modifyInfo.lockedPlugins.size() > 0 ) {
			final boolean ret[] = new boolean[1];
			SafeUpdateController.syncExec(new Runnable() {
				public void run() {
					String WIZARD_TITLE = ImportXMLResources.importXMLWizard_title; 
					String message = modifyInfo.getLockedMessage().toString() +
						ImportResources.ImportPluginWizard_confirm_continue; 
					ret[0] = ImportXMLPlugin
							.getDefault().getMsgDialog().displayConfirmation(WIZARD_TITLE, message);
				}
			});		
			return ret[0];
		} 			
		return true;
	}
	
	/**
	 * @return the log file.
	 */
	public File getLogPath() {
		return logger.getLogPath();
	}

	/**
	 * Dispose
	 */
	public void dispose() {

		discardedElements.clear();
		workOrderMap.clear();
		logger.dispose();
	}

	/**
	 * Does XML export.
	 * @param monitor
	 * @throws Exception
	 */
	public void doImport(IProgressMonitor monitor) throws Exception {
		boolean refresh = RefreshJob.getInstance().isEnabled();
		try {
			if (refresh) {
				// disable resource refreshing during import
				//
				RefreshJob.getInstance().setEnabled(false);
			}
			
			handleTypeChanges();
			
			IResourceHandler handler = new ImportResourceHandler(new File(
					xmlPath).getParentFile(), new File(LibraryService
					.getInstance().getCurrentMethodLibraryPath()));

			ContentProcessor contentProc = new ContentProcessor(handler,
					this.logger);
			
			diagramHandler = new DiagramHandler(new File(
					xmlPath).getParentFile(), new File(LibraryService
							.getInstance().getCurrentMethodLibraryPath()));

			this.xmlLib.fixLibraryForImport();

			// make sure all the dependent plugins are there
			List referencedPlugins = xmlLib.getReferencedPlugins();
			if (referencedPlugins.size() > 0) {
				org.eclipse.epf.uma.MethodLibrary library = org.eclipse.epf.library.LibraryService
						.getInstance().getCurrentMethodLibrary();
				if (library != null) {
					List plugins = library.getMethodPlugins();
					for (Iterator it = plugins.iterator(); it.hasNext();) {
						String id = ((org.eclipse.epf.uma.MethodPlugin) it
								.next()).getGuid();
						referencedPlugins.remove(id);
					}
				}
			}

			if (referencedPlugins.size() > 0) {
				for (Iterator it = referencedPlugins.iterator(); it.hasNext();) {
					String id = (String) it.next();
					logger.logError(NLS.bind(ImportXMLResources.importXMLService_missing_plugin, id),
							null);
				}

				throw new Exception(
						ImportXMLResources.importXMLService_error_missing_plugins);
			}

			this.umaLib = new UmaLibrary(contentProc, logger, overwrite);

			EDataObject xmlRoot = this.xmlLib.getRoot();
			EDataObject umaRoot = this.umaLib.getRoot();
			
			logger.logMessage("create target library elements ..."); //$NON-NLS-1$
			creatEDataObjectTree(xmlRoot, umaRoot);

			logger
					.logMessage("copying all feature values for target library elements ..."); //$NON-NLS-1$
			iteratEDataObject((MethodElement) xmlRoot);

			logger.logMessage("fix the target library ..."); //$NON-NLS-1$
			umaLib.fixLibrary();

			LibraryImportManager.handleNameReplace(renameElementMap);
			
			// delete the un-needed elements
			logger.logMessage("delete unneeded elements ..."); //$NON-NLS-1$
			umaLib.deleteElements();
			
			final List modifiedFiles = FileModifyChecker.getModifiedFiles(LibraryService.getInstance().
										getCurrentMethodLibrary().eResource().getResourceSet());
			modifiedFiles.addAll(diagramHandler.getModifiedFiles());
			final IStatus fileCheckedOutStatus = FileModifyChecker.syncExecCheckModify(modifiedFiles);
			
			if (fileCheckedOutStatus.isOK()) {
			
				logger.logMessage("saving target library ..."); //$NON-NLS-1$
	
				List configs = LibraryService.getInstance()
				.getCurrentMethodLibrary().getPredefinedConfigurations();
				int configSz = configs == null ? 0 : configs.size();
				for (int i=0; i<configSz; i++) {
					org.eclipse.epf.uma.MethodConfiguration config = 
						(org.eclipse.epf.uma.MethodConfiguration ) configs.get(i);
					LibraryUtil.validateMethodConfiguration(config);
				}
				
				// don't refresh the workspace
				LibraryUtil.saveLibrary(LibraryService.getInstance()
						.getCurrentMethodLibrary(), false, false);
				diagramHandler.execute();				
	
				logger.logMessage("re-open target library ..."); //$NON-NLS-1$
				LibraryService.getInstance().reopenCurrentMethodLibrary();
	
				logger.logMessage("import completed successfully ..."); //$NON-NLS-1$
			} else {
				SafeUpdateController.syncExec(new Runnable() {
					public void run() {
						String title = ImportXMLResources.importXMLWizard_title; 
						String msg = ImportXMLResources.importXMLService_import_failed; 
						new MsgDialog(ImportXMLPlugin.getDefault())
							.displayError(title, msg, fileCheckedOutStatus);
						}
				});
			}	
						
			//ResourceUtil.refreshResources(LibraryService.getInstance()
			//		.getCurrentMethodLibrary(), monitor);

		} catch (Exception e) {
			logger.logError(NLS.bind(ImportXMLResources.importXMLService_import_failed, e.getMessage()), e);

			throw e;

		} finally {
			if (refresh) {
				// re-enable resource refreshing
				//
				RefreshJob.getInstance().setEnabled(true);
			}
		}
	}

	private void creatEDataObjectTree(EDataObject xmlObj, EDataObject umaObj) {

		for (Iterator it = xmlObj.eContents().iterator(); it.hasNext();) {
			EDataObject child = (EDataObject) it.next();
			createRmcObject(child, umaObj);
		}
	}

	private void createRmcObject(EDataObject xmlElement,
			EDataObject targetContainer) {

		// get the targetContainer's containing feature
		EStructuralFeature feature = xmlElement.eContainmentFeature();
		createRmcObject(xmlElement, targetContainer, feature.getName());
	}

	private void createRmcObject(EDataObject xmlElement,
			EDataObject targetContainer, String containmentXmlFeature) {

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

			EDataObject umaElement = null;

			// don't create content category package since in uma, it's
			// seperated based on type
			if (xmlElement instanceof MethodPlugin) {
				MethodPlugin plugin = (MethodPlugin) xmlElement;
				umaElement = umaLib.createMethodPlugin(plugin.getId(), plugin
						.getName());
			} else if (xmlElement instanceof ContentCategoryPackage) {
				// don't create, do nothing
				// mark as discarded so we don't need to copy it's attributes
				setDiscarded(((ContentCategoryPackage) xmlElement).getId());

			} else if ((xmlElement instanceof ContentCategory)
					&& !(xmlElement.eContainer() instanceof Domain 
							|| xmlElement.eContainer() instanceof Discipline)
					|| (xmlElement.eContainer() instanceof ContentCategoryPackage)) {
				// create the content categories for root content categories,
				// not for sub-domain and sub-discipline
				// 154143 - import xml did not reserve the sub-discipline structure
				String pluginId = getPlugin(xmlElement).getId();
				umaElement = umaLib.createContentCategory(pluginId, xmlElement
						.eClass().getName(), xmlElement.getType().getName(),
						xmlLib.getElementId(xmlElement));
			} else {

				// if this is root level package, find the corresponding
				// container for the UMA object
				if (xmlElement instanceof MethodPackage
						&& xmlElement.eContainer() instanceof MethodPlugin) {
					if (xmlElement instanceof ContentPackage) {
						targetContainer = umaLib
								.getContentRootPackage(targetContainer);
					} else if (xmlElement instanceof ProcessComponent) {
						Object proc = ((ProcessComponent) xmlElement)
								.getProcess();
						if (proc instanceof CapabilityPattern) {
							targetContainer = umaLib
									.getCapabilityPatternRootPackage(targetContainer);
						} else if (proc instanceof DeliveryProcess) {
							targetContainer = umaLib
									.getDeliveryProcessRootPackage(targetContainer);
						}
					} else if (xmlElement instanceof ProcessPackage) {
						List procs = xmlLib
								.getAllProcesses((MethodPackage) xmlElement);
						if (procs != null && procs.size() > 0) {
							Object proc = procs.get(0);
							if (proc instanceof CapabilityPattern) {
								targetContainer = umaLib
										.getCapabilityPatternRootPackage(targetContainer);
							} else if (proc instanceof DeliveryProcess) {
								targetContainer = umaLib
										.getDeliveryProcessRootPackage(targetContainer);
							}
						}
					}
				}
				// get the containment feature so we can create the object of
				// the same type
				umaElement = umaLib.createElement(targetContainer,
						containmentXmlFeature, xmlElement.eClass().getName(),
						xmlElement.getType().getName(), xmlLib
								.getElementId(xmlElement));

				// xml WorkOrder does not have an id, need to map the uma Object
				if (xmlElement instanceof WorkOrder) {
					workOrderMap.put(xmlElement, umaElement);
				}
			}

			// recursive,
			// note, uma element might be null since we can't determine the
			// owner of the element yet
			creatEDataObjectTree(xmlElement, umaElement);

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

	private MethodPlugin getPlugin(EObject element) {
		while ((element != null) && !(element instanceof MethodPlugin)) {
			element = element.eContainer();
		}

		return (MethodPlugin) element;
	}

	private EDataObject getRmcObject(MethodElement xmlObj) {
		if (xmlObj instanceof MethodLibrary) {
			return umaLib.getRoot();
		} else {
			String id = xmlObj.getId();
			return this.umaLib.getElement(id);
		}
	}

	private void iteratEDataObject(MethodElement srcObj) {
		iteratEDataObject_(srcObj);
		EDataObject targetObj = getRmcObject(srcObj);
		if (targetObj instanceof org.eclipse.epf.uma.MethodElement) {
			diagramHandler.registerElement((org.eclipse.epf.uma.MethodElement) targetObj); 
		}
	}
	
	private void iteratEDataObject_(MethodElement srcObj) {

		logger
				.logMessage(" === processing element " + srcObj.getType().getName() + ": " + srcObj.getName()); //$NON-NLS-1$ //$NON-NLS-2$

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

		// if object is not created, it's xml wrapper package
		if (srcObj instanceof ContentCategoryPackage) {

			// iterate the child packages
			for (Iterator it = ((ContentCategoryPackage) srcObj)
					.getContentCategory().iterator(); it.hasNext();) {
				iteratEDataObject((MethodElement) it.next());
			}
			return;
		}

		EDataObject targetObj = getRmcObject(srcObj);
		EClass eClass = srcObj.eClass();

		EList features = eClass.getEAllStructuralFeatures();
		boolean isNewElement = umaLib.isNewElement(srcObj.getId()) || srcObj instanceof MethodLibrary;
		boolean isOldPlugin = !isNewElement && (srcObj instanceof MethodPlugin);
		
		for (Iterator it = features.iterator(); it.hasNext();) {
			EStructuralFeature feature = (EStructuralFeature) it.next();
						
			if (FeatureManager.INSTANCE.isUnneededXmlFeature(feature.getName())) {
				continue;
			}
			if (isOldPlugin && UmaPackage.eINSTANCE.getMethodPlugin_UserChangeable() == feature) {
				continue;
			}

			Object value = srcObj.eGet(feature);
			if (value == null) {
				continue;
			}

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

						if (src_value instanceof String) {

							// it's an id reference
							umaLib.setReferenceValue(targetObj, feature
									.getName(), (String) src_value);
						} else if (src_value instanceof MethodElement) {
							// set the reference
							MethodElement e = (MethodElement) src_value;
							String guid = e.getId();

							// don't set the containment feature value since
							// it's already handled
							// when creating the library structure
							if (!isDiscarded(guid) && e.eContainer() != srcObj) {
								umaLib.setReferenceValue(targetObj, feature
										.getName(), guid);
							}

							iteratEDataObject((MethodElement) src_value);
						} else if (src_value instanceof WorkOrder) {
							// WorkOrder is not method element and does not have
							// an id, need special handling
							// set the prede
							WorkOrder wr = (WorkOrder) src_value;
							Object umaWr = workOrderMap.get(wr);
							umaLib.setWorkOrder(umaWr, wr.getValue());
						} else {
							logger
									.logMessage(NLS.bind(ImportXMLResources.importXMLService_element_not_handled, src_value));
						}
					}
				} else if (feature instanceof EReference) {

					// get the xml object and iterate again
					Object src_value = value;

					if (src_value instanceof WorkOrder) {
						logger.logMessage("workorder value"); //$NON-NLS-1$
					} else if (src_value instanceof String
							&& !isDiscarded((String) src_value)) {
						// it's an id reference
						umaLib.setReferenceValue(targetObj, feature.getName(),
								(String) src_value);
					} else if (src_value instanceof MethodElement) {
						// set the reference
						String guid = ((MethodElement) src_value).getId();
						if (guid == null) {
							logger
									.logWarning(NLS.bind(ImportXMLResources.importXMLService_element_without_id, ((MethodElement) src_value)
									.getName()));
						}
						if (!isDiscarded(guid)) {
							umaLib.setReferenceValue(targetObj, feature
									.getName(), guid);
						}
						iteratEDataObject((MethodElement) src_value);
					} else {
						logger
								.logWarning(NLS.bind(ImportXMLResources.importXMLService_element_not_handled, src_value));
					}

				} else {
					if (targetObj instanceof ContentCategoryPackage) {
						logger.logMessage("hrre"); //$NON-NLS-1$
					}

					if (value instanceof WorkOrderType) {
						value = ((WorkOrderType) value).getName();
					}
					
					boolean rename = false;
					if (!isNewElement && feature == org.eclipse.epf.xml.uma.UmaPackage.eINSTANCE.getNamedElement_Name()) {
						String oldName = (String)targetObj.eGet(org.eclipse.epf.uma.UmaPackage.eINSTANCE.getNamedElement_Name());
						String newName = (String)srcObj.eGet(feature);				
						if (!newName.equals(oldName)) {
							LibraryImportManager.ensureUniqueNameForExistingElement
								((org.eclipse.epf.uma.MethodElement) targetObj, oldName, newName, renameElementMap);
							rename = true;
						}
					}
					if (!rename) {
						umaLib.setAtributeFeatureValue(targetObj,
								feature.getName(), value);
					}
					if (isNewElement && feature == org.eclipse.epf.xml.uma.UmaPackage.eINSTANCE.getNamedElement_Name()) {
						org.eclipse.epf.uma.MethodElement elem = (org.eclipse.epf.uma.MethodElement) targetObj;
						EObject ceobj = elem.eContainer();						
						if (ceobj instanceof org.eclipse.epf.uma.MethodElement && 
								! umaLib.isNewElement(((org.eclipse.epf.uma.MethodElement) ceobj).getGuid())) {
							LibraryImportManager.ensureUniqueName(ceobj, elem, renameElementMap);
						}
					}

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

		}

	}

	// 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 boolean isDiscarded(String id) {
		return discardedElements.contains(id);
	}

	private void setDiscarded(String id) {
		discardedElements.add(id);
	}
	
	/**
	 * Sets overwrite attribute.
	 * @param b
	 */
	public void setOverwrite(boolean b) {
		overwrite = b;
	}	
	
	private static String versionCheck(final String xmlPath, final String title) {
		final String[] ret = new String[1];
		ret[0] = null;
		SafeUpdateController.syncExec(new Runnable() {	
			public void run() {				
				VersionUtil.VersionCheckInfo info = VersionUtil.checkXMLVersion(new File(xmlPath));
				if (info == null) {
					ret[0] = NLS.bind(ImportXMLResources.versionMismatch_oldData_unknown, new Object[] {
							Platform.getProduct().getName()});					
				} else {
					if (info.result < 0) {
						if (info.toolID.equals(VersionUtil.getPrimaryToolID())) {
							ret[0] = NLS.bind(ImportXMLResources.versionMismatch_oldData, new Object[] {
									info.toolVersion, Platform.getProduct().getName()});
						} else {
							ret[0] = NLS.bind(ImportXMLResources.versionMismatch_oldData_unknown, new Object[] {
									Platform.getProduct().getName()});					
						}
					} else if (info.result > 0) {
						if (info.toolID.equals(VersionUtil.getPrimaryToolID())) {
							ret[0] = NLS.bind(ImportXMLResources.versionMismatch_oldTool, new Object[] {
								info.toolVersion, Platform.getProduct().getName()});
						} else {
							ret[0] = NLS.bind(ImportXMLResources.versionMismatch_oldTool_unknown, new Object[] {
									Platform.getProduct().getName()});
						}
					} 
				}
				if (ret[0] != null) {
					ImportXMLPlugin.getDefault().getMsgDialog().displayError(title, ret[0]);					
				}
			}
		});		
		return ret[0];
	}
	
	 public void handleTypeChanges() {
		org.eclipse.epf.uma.MethodLibrary baseLib = LibraryService.getInstance()
												.getCurrentMethodLibrary();
		HashMap baseMap = new HashMap();
		ConfigurationImportService.collectPotentialTypeChanged(baseLib, baseMap);
		
		HashMap eClassObjMap = new HashMap();
		HashMap importMap = new HashMap();
		for (Iterator it = xmlLib.getRoot().eAllContents(); it.hasNext();) {
			Object obj = it.next();
			if (obj instanceof Guidance ||
				obj instanceof Activity) {
				MethodElement xmlElement = (MethodElement) obj;
				String eClassName = xmlElement.eClass().getName();
				Object eClassObj = eClassObjMap.get(eClassName);
				if (eClassObj == null) {
					EClass objEClass = FeatureManager.INSTANCE.getRmcEClass(eClassName);
					if (objEClass != null) {
						eClassObj = UmaFactory.eINSTANCE.create(objEClass);
						eClassObjMap.put(eClassName, eClassObj);	
					}
				}
				if (eClassObj != null) {
					importMap.put(xmlElement.getId(), eClassObj);
				}
			}
		}
		
		ConfigurationImportService.handleTypeChanges(baseMap, importMap);	
	}
	
}
