//------------------------------------------------------------------------------
// 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.library.xmi.internal.migration;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.util.EContentsEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.EContentsEList.FeatureIterator;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.epf.common.serviceability.MsgBox;
import org.eclipse.epf.diagram.model.util.GraphicalDataHelper;
import org.eclipse.epf.diagram.model.util.GraphicalDataManager;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.util.ModelStructure;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.util.ResourceUtil;
import org.eclipse.epf.library.xmi.XMILibraryPlugin;
import org.eclipse.epf.library.xmi.XMILibraryResources;
import org.eclipse.epf.persistence.MethodLibraryPersister;
import org.eclipse.epf.persistence.MultiFileResourceSetImpl;
import org.eclipse.epf.persistence.MultiFileSaveUtil;
import org.eclipse.epf.persistence.MultiFileXMISaveImpl;
import org.eclipse.epf.persistence.migration.IMigrator;
import org.eclipse.epf.persistence.migration.MigrationResourceHandler;
import org.eclipse.epf.persistence.migration.MigrationUtil;
import org.eclipse.epf.persistence.migration.UpgradeCallerInfo;
import org.eclipse.epf.persistence.util.PersistenceResources;
import org.eclipse.epf.persistence.util.PersistenceUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.Diagram;
import org.eclipse.epf.uma.GraphNode;
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.Property;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.SemanticModelBridge;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.UMASemanticModelBridge;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;

/**
 * @author Phong Nguyen Le - Jun 12, 2006
 * @since 1.0
 */
public class Migrator102 implements IMigrator {
	private static final boolean DEBUG = XMILibraryPlugin.getDefault()
			.isDebugging();

	private static void updateStatus(IProgressMonitor monitor, String msg) {
		if (monitor != null) {
			monitor.subTask(msg);
			monitor.worked(1);
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				//
			}
		} else {
			System.out.println(msg);
		}
	}

	private Collection proxiesToRemove = new ArrayList();

	private Map proxyToFileMap = new HashMap();

	private HashMap proxyToFileWithLoadErrorMap = new HashMap();

	private ArrayList notFoundProxies = new ArrayList();

	private ArrayList proxiesWithUnnormalizedURI = new ArrayList();

	private MethodLibrary lib;

	private MigrationResourceHandler resourceHandler = new MigrationResourceHandler() {

		protected boolean handleUnknownFeature(EObject owner,
				EStructuralFeature feature, Object value) {
			// Order graph nodes of task descriptors in ADD based on their order
			// in the task descriptor list of the role descriptor
			// old feature: RoleDescriptor.performsAsOwner
			//
			if(owner instanceof RoleDescriptor
					&& "performsAsOwner".equals(feature.getName()) //$NON-NLS-1$
					&& value != null)
			{
				ArrayList GUIDs = new ArrayList();
				StringTokenizer tokens = new StringTokenizer((String) value);
				while(tokens.hasMoreTokens()) {
					GUIDs.add(tokens.nextToken());
				}
				if(GUIDs.size() > 1) {
					Activity act = ((RoleDescriptor)owner).getSuperActivities();
					Diagram add = GraphicalDataManager.getInstance().getUMADiagram(act, GraphicalDataHelper.ACTIVITY_DETAIL_DIAGRAM, false);
					if(add != null) {
						Map tdGuidToGraphNodeMap = new HashMap();
						int size = add.getContained().size();
						for (int i = 0; i < size; i++) {
							Object element = add.getContained().get(i);
							if(element instanceof GraphNode) {
								GraphNode graphNode = ((GraphNode)element);
								SemanticModelBridge bridge = graphNode.getSemanticModel();
								if (bridge instanceof UMASemanticModelBridge) {
									MethodElement me = ((UMASemanticModelBridge) bridge).getElement();								
									if(me instanceof TaskDescriptor) {
										List list = graphNode.getList(UmaPackage.GRAPH_NODE__PROPERTY);
										Property property = GraphicalDataHelper.getPropertyByKey(list,
												GraphicalDataHelper.PROP_WORK_PRODUCT_COMPOSITE_TYPE);
										if (property == null) {
											// this is not a GraphNode for WorkProductComposite
											// it must be a GraphNode for a TaskDescriptor
											//
											tdGuidToGraphNodeMap.put(me.getGuid(), graphNode);
										}
									}
								}
							}
						}
						
						// reorder the graph nodes to match order of their linked task descriptors
						//
						ArrayList graphNodes = new ArrayList();
						for(int i = 0; i < GUIDs.size(); i++) {
							Object graphNode = tdGuidToGraphNodeMap.get(GUIDs.get(i));
							if(graphNode != null) {
								graphNodes.add(graphNode);
							}
						}
						add.getContained().removeAll(graphNodes);
						add.getContained().addAll(graphNodes);
					}					
				}
			}
			return true;
		}

	};

	private static final String FILE_PATH = XMILibraryResources.filePath;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.persistence.migration.IMigrator#migrate(java.lang.String,
	 *      org.eclipse.core.runtime.IProgressMonitor)
	 */
	public void migrate(String libPath, IProgressMonitor monitor)
		throws Exception {
		migrate(libPath, monitor, null);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.epf.persistence.migration.IMigrator#migrate(java.lang.String, org.eclipse.core.runtime.IProgressMonitor, org.eclipse.epf.persistence.migration.UpgradeCallerInfo)
	 */
	public void migrate(String libPath, IProgressMonitor monitor, UpgradeCallerInfo info)
			throws Exception {
		File libFile = new File(libPath);

		boolean toVerify = true;
		if (info != null && info.getIsExportedPluginLib()) {
			toVerify = false;
		}
		
		ResourceUtil.open(libFile.getParent(), monitor);

		MultiFileResourceSetImpl resourceSet = null;
		try {
			// set 1.0.2 default values so data can be correctly loaded
			//
			setOldDefaultValues();

			// load the library
			//
			updateStatus(monitor, PersistenceResources.loadLibraryTask_name);

			if (toVerify) {
				resourceSet = new MultiFileResourceSetImpl(false);
			} else {
				resourceSet = new MultiFileResourceSetImpl(false) {
					protected void demandLoad(Resource resource) throws IOException {
						if (! skipDemandLoad(resource)) {
							super.demandLoad(resource);
						}
					}
					private boolean skipDemandLoad(Resource res) {
						File file = new File(res.getURI().toFileString());
						if (! file.exists() && file.getName().equals(MultiFileSaveUtil.DEFAULT_PLUGIN_MODEL_FILENAME)) {
							return true;
						}
						return false;
					}
				};
			}
						
			resourceSet.getLoadOptions().put(
					XMLResource.OPTION_RECORD_UNKNOWN_FEATURE, Boolean.TRUE);
			resourceSet.getLoadOptions().put(
					XMLResource.OPTION_RESOURCE_HANDLER, resourceHandler);
			lib = resourceSet.loadLibrary(libPath);
			
			removeProcessContributions(monitor);

			// verify the library
			//
			// TODO: uncomment after externalize the text
			// updateStatus(monitor, "Verifying...");

			if (toVerify) {
				Display dis = Display.getDefault();
				if (dis == null || dis.getThread() == Thread.currentThread()) {
					verify();
				} else {
					dis.syncExec(new Runnable() {
						public void run() {
							verify();
						}
					});
				}
				removeUnresolvedReferences(monitor);
			}
			
			// load all elements in memory
			//
			updateStatus(monitor, PersistenceResources.loadResourcesTask_name);
			for (Iterator iter = lib.eAllContents(); iter.hasNext();) {
				EObject element = (EObject) iter.next();
				if (element instanceof MethodElement) {
					try {
						for (Iterator iterator = element.eCrossReferences()
								.iterator(); iterator.hasNext();) {
							iterator.next();
						}
					} catch (Exception e) {
						CommonPlugin.INSTANCE.log(e);
						if (DEBUG) {
							System.err
									.println("Error iterate thru cross references of element: " + element); //$NON-NLS-1$
						}
					}
					update((MethodElement) element, monitor);
				}
			}

			
			
			removeOldDefaultValues();

			// check modified resources for writable before saving them
			//
			Display dis = Display.getDefault();
			if (dis == null || dis.getThread() == Thread.currentThread()) {
				checkModifiedResources();
			} else {
				dis.syncExec(new Runnable() {
					public void run() {
						checkModifiedResources();
					}
				});
			}

			// save all files
			//
			updateStatus(monitor, PersistenceResources.saveLibraryTask_name);
			Map saveOptions = resourceSet.getDefaultSaveOptions();
			if (toVerify) {
				saveOptions.put(MultiFileXMISaveImpl.DISCARD_UNRESOLVED_REFERENCES,
					Boolean.TRUE);
			}
			resourceSet.save(saveOptions, true);

			updateStatus(monitor,
					PersistenceResources.refreshLibraryFilesTask_name);
			ResourceUtil.refreshResources(lib, monitor);
		} finally {
			if (resourceSet != null) {
				resourceSet.reset();
				resourceSet = null;
			}
		}
	}

	/**
	 * Removes process contributions from all plugins
	 */
	private void removeProcessContributions(IProgressMonitor monitor) {
		for (Iterator iter = lib.getMethodPlugins().iterator(); iter.hasNext();) {
			MethodPlugin plugin = (MethodPlugin) iter.next();
			MethodPackage pkg = UmaUtil.findMethodPackage(plugin,
					ModelStructure.DEFAULT.processContributionPath);
			if (pkg != null) {
				for (Iterator iterator = new ArrayList(pkg.getChildPackages())
						.iterator(); iterator.hasNext();) {
					MethodPackage childPkg = (MethodPackage) iterator.next();
					Resource resource = ((InternalEObject) childPkg)
							.eDirectResource();
					if (resource != null) {
						ResourceSet resourceSet = resource.getResourceSet();
						try {
							MethodLibraryPersister.INSTANCE.delete(pkg);
						} catch (Exception e) {
							if (DEBUG) {
								e.printStackTrace();
							}
						}
						if (resourceSet != null) {
							resourceSet.getResources().remove(resource);
						}
					}
				}
				pkg.getChildPackages().clear();
			}
		}
	}

	/**
	 * 
	 */
	private void checkModifiedResources() {
		do {
			ResourceSet resourceSet = lib.eResource().getResourceSet();
			ArrayList readOnlyResources = new ArrayList();
			String pluginId = XMILibraryPlugin.getDefault().getId();
			MultiStatus status = new MultiStatus(pluginId, 0,
					XMILibraryResources.cannotWriteToFiles, null);
			for (Iterator iter = resourceSet.getResources().iterator(); iter
					.hasNext();) {
				Resource resource = (Resource) iter.next();
				File file = new File(resource.getURI().toFileString());
				if (file.exists() && !file.canWrite()) {
					readOnlyResources.add(resource);
					status.add(new Status(IStatus.ERROR, pluginId, 0, file
							.toString(), null));
				}
			}
			if (!status.isOK()) {
				String title = XMILibraryResources.readOnlyFiles_title;
				String msg = XMILibraryResources.readOnlyFiles_msg;
				ErrorDialog errDlg = new ErrorDialog(MsgBox.getDefaultShell(),
						title, msg, status, IStatus.OK | IStatus.INFO
								| IStatus.WARNING | IStatus.ERROR) {
					/*
					 * (non-Javadoc)
					 * 
					 * @see org.eclipse.jface.dialogs.ErrorDialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
					 */
					protected void createButtonsForButtonBar(Composite parent) {
						// create Retry, Cancel and Details buttons
						createButton(parent, IDialogConstants.OK_ID,
								IDialogConstants.RETRY_LABEL, true);

						createButton(parent, IDialogConstants.CANCEL_ID,
								IDialogConstants.CANCEL_LABEL, false);

						createDetailsButton(parent);
					}

					/*
					 * (non-Javadoc)
					 * 
					 * @see org.eclipse.jface.dialogs.ErrorDialog#open()
					 */
					public int open() {
						showDetailsArea();
						return super.open();
					}

				};
				if (errDlg.open() == IDialogConstants.CANCEL_ID) {
					throw new OperationCanceledException();
				}
			} else {
				return;
			}
		} while (true);
	}

	/**
	 * @param monitor
	 */
	private void removeUnresolvedReferences(IProgressMonitor monitor) {
		if (proxiesToRemove.isEmpty())
			return;
		// TODO: uncomment after externalize the text
		// updateStatus(monitor, "Removing unresolved references");
		HashSet GUIDs = new HashSet();
		for (Iterator iter = proxiesToRemove.iterator(); iter.hasNext();) {
			InternalEObject proxy = (InternalEObject) iter.next();
			GUIDs.add(proxy.eProxyURI().fragment());
			EcoreUtil.remove(proxy);
		}
		for (Iterator iter = lib.eAllContents(); iter.hasNext();) {
			EObject element = (EObject) iter.next();
			for (EContentsEList.FeatureIterator iterator = (FeatureIterator) element
					.eCrossReferences().iterator(); iterator.hasNext();) {
				InternalEObject obj = (InternalEObject) iterator.next();
				if (obj.eIsProxy()
						&& GUIDs.contains(obj.eProxyURI().fragment())) {
					EStructuralFeature feature = iterator.feature();
					if (feature.isChangeable() && !feature.isDerived()) {
						if (feature.isMany()) {
							((List) element.eGet(feature)).remove(obj);
						} else {
							element.eSet(feature, null);
						}
					}
				}
			}
		}
	}

	/**
	 * @param lib
	 */
	private void verify() {
		notFoundProxies.clear();
		proxiesToRemove.clear();
		proxyToFileMap.clear();
		proxyToFileWithLoadErrorMap.clear();
		proxiesWithUnnormalizedURI.clear();

		Collection<EObject> proxies = PersistenceUtil.getProxies(lib);
		if (!proxies.isEmpty()) {
			ResourceSet resourceSet = lib.eResource().getResourceSet();
			URIConverter uriConverter = resourceSet.getURIConverter();
			for (Iterator iter = proxies.iterator(); iter.hasNext();) {
				InternalEObject proxy = (InternalEObject) iter.next();
				URI uri = proxy.eProxyURI();
				URI normalizedURI = uriConverter.normalize(uri);
				if (normalizedURI == null) {
					proxiesWithUnnormalizedURI.add(proxy);
				} else {
					File file = new File(normalizedURI.toFileString());
					if (!file.exists()) {
						proxyToFileMap.put(proxy, file);
					} else {
						try {
							Resource resource = resourceSet.getResource(
									normalizedURI.trimFragment(), true);
							if (resource.getEObject(normalizedURI.fragment()) == null) {
								notFoundProxies.add(proxy);
							}
						} catch (Exception e) {
							String errMsg = e.getMessage() != null ? e
									.getMessage() : e.toString();
							proxyToFileWithLoadErrorMap.put(proxy,
									new Object[] { file, errMsg });
						}
					}
				}
			}
		}

		if (!proxyToFileMap.isEmpty()) {
			// promp user to resolve missing files
			//
			List list = new ArrayList(proxyToFileMap.keySet());
			final String ELEMENT_PATH = XMILibraryResources.elementPath;
			ILabelProvider labelProvider = new AdapterFactoryLabelProvider(
					TngAdapterFactory.INSTANCE
							.getNavigatorView_ComposedAdapterFactory()) {

				/*
				 * (non-Javadoc)
				 * 
				 * @see org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider#getText(java.lang.Object)
				 */
				public String getText(Object object) {
					File file = (File) proxyToFileMap.get(object);
					return file.getAbsolutePath()
							+ " (" + TngUtil.getLabelWithPath(object) + ')'; //$NON-NLS-1$
				}

				/*
				 * (non-Javadoc)
				 * 
				 * @see org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider#getColumnText(java.lang.Object,
				 *      int)
				 */
				public String getColumnText(Object object, int columnIndex) {
					switch (columnIndex) {
					case 0:
						return proxyToFileMap.get(object).toString();
					case 1:
						return TngUtil.getLabelWithPath(object);
					}
					return null;
				}

			};

			try {
				String msg = XMILibraryResources.promptRemoveReferencesToMissingFiles_msg;
				SelectionDialog dlg = new SelectionDialog(MsgBox
						.getDefaultShell(), list, labelProvider, msg);

				dlg.setTitle(XMILibraryResources.missingFiles_title);
				dlg.setBlockOnOpen(true);
				dlg.setInitialElementSelections(list);
				dlg
						.setColumnProperties(new String[] { FILE_PATH,
								ELEMENT_PATH });
				if (dlg.open() == Dialog.CANCEL) {
					throw new OperationCanceledException();
				}
				Object objs[] = dlg.getResult();
				if (objs == null) {
					throw new OperationCanceledException();
				} else {
					for (Iterator iter = list.iterator(); iter.hasNext();) {
						proxiesToRemove.add(iter.next());

					}
				}
			} finally {
				labelProvider.dispose();
			}
		}

		// prompt user to resolve files that can not be loaded
		//
		if (!proxyToFileWithLoadErrorMap.isEmpty()) {
			List list = new ArrayList(proxyToFileWithLoadErrorMap.keySet());
			final String LOAD_ERROR = XMILibraryResources.loadError;
			ILabelProvider labelProvider = new AdapterFactoryLabelProvider(
					TngAdapterFactory.INSTANCE
							.getNavigatorView_ComposedAdapterFactory()) {

				/*
				 * (non-Javadoc)
				 * 
				 * @see org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider#getColumnText(java.lang.Object,
				 *      int)
				 */
				public String getColumnText(Object object, int columnIndex) {
					Object[] arr = (Object[]) proxyToFileMap.get(object);
					if (columnIndex < 2) {
						return arr[columnIndex].toString();
					}
					return null;
				}

			};

			try {
				String msg = XMILibraryResources.promptRemoveReferencesToFilesWithLoadErrors_msg;
				SelectionDialog dlg = new SelectionDialog(MsgBox
						.getDefaultShell(), list, labelProvider, msg);

				dlg.setTitle(XMILibraryResources.filesWithLoadErrors_title);
				dlg.setBlockOnOpen(true);
				dlg.setInitialElementSelections(list);
				dlg.setColumnProperties(new String[] { FILE_PATH, LOAD_ERROR });
				if (dlg.open() == Dialog.CANCEL) {
					throw new OperationCanceledException();
				}
				Object objs[] = dlg.getResult();
				if (objs == null) {
					throw new OperationCanceledException();
				} else {
					for (Iterator iter = list.iterator(); iter.hasNext();) {
						proxiesToRemove.add(iter.next());

					}
				}
			} finally {
				labelProvider.dispose();
			}
		}

		ArrayList proxiesToRetain = new ArrayList();
		proxies.addAll(proxyToFileMap.keySet());
		proxies.addAll(proxyToFileWithLoadErrorMap.keySet());
		proxies.removeAll(proxiesToRemove);

		if (proxiesToRetain.isEmpty()) {
			proxiesToRemove.addAll(notFoundProxies);
			proxiesToRemove.addAll(proxiesWithUnnormalizedURI);
		}

		String msg = "Summary of unresolved proxies:"; //$NON-NLS-1$
		msg += "\n  Not found proxies: " + notFoundProxies; //$NON-NLS-1$
		msg += "\n  Proxies with unnormalized URI: " + proxiesWithUnnormalizedURI; //$NON-NLS-1$
		XMILibraryPlugin.getDefault().getLogger().logInfo(msg);
	}

	/**
	 * 
	 */
	private void removeOldDefaultValues() {
		MultiResourceEObject.removeDefaultValue(UmaPackage.eINSTANCE
				.getMethodPlugin_UserChangeable());
	}

	/**
	 * @param e
	 * 
	 */
	private void adjustToNewDefaultValues(MethodElement e) {
		if (e instanceof MethodPlugin) {
			((MultiResourceEObject) e)
					.removeFeatureWithOverridenDefaultValue(UmaPackage.eINSTANCE
							.getMethodPlugin_UserChangeable());
		}
	}

	/**
	 * 
	 */
	private void setOldDefaultValues() {
		MultiResourceEObject.setDefaultValue(UmaPackage.eINSTANCE
				.getMethodPlugin_UserChangeable(), Boolean.FALSE);
	}

	private void update(MethodElement e, IProgressMonitor monitor)
			throws Exception {
		adjustToNewDefaultValues(e);

		if (e instanceof Activity) {
			Activity act = (Activity) e;
			VariabilityType type = act.getVariabilityType();
			if (type == VariabilityType.CONTRIBUTES_LITERAL) {
				act
						.setVariabilityType(VariabilityType.LOCAL_CONTRIBUTION_LITERAL);
			} else if (type == VariabilityType.REPLACES_LITERAL) {
				act
						.setVariabilityType(VariabilityType.LOCAL_REPLACEMENT_LITERAL);
			}
		}
		MigrationUtil.formatValue(e);
	}

}
