//------------------------------------------------------------------------------
// 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.ui.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.ui.util.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.layout.LinkInfo;
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.MigrationResourceHandler;
import org.eclipse.epf.persistence.migration.MigratorImpl;
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 extends MigratorImpl {
	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 {
		initMigrate();
		
		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 = getImportPluginResourceSet();
			}
						
			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);
			}
						
			if (this instanceof Migrator102_103) {
				LinkInfo.setLibrary(lib);
			}
			// 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);
			migrateDiagram(monitor);
		} finally {
			if (this instanceof Migrator102_103) {
				LinkInfo.setLibrary(null);
			}
			if (resourceSet != null) {
				resourceSet.reset();
				resourceSet = null;
			}
		}
	}

	protected static MultiFileResourceSetImpl getImportPluginResourceSet() {
		MultiFileResourceSetImpl resourceSet;
		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;
			}
		};
		return resourceSet;
	}

	/**
	 * 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);
	}

	protected 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) {
				act
						.setVariabilityType(VariabilityType.LOCAL_CONTRIBUTION);
			} else if (type == VariabilityType.REPLACES) {
				act
						.setVariabilityType(VariabilityType.LOCAL_REPLACEMENT);
			}
		}
		if (! (this instanceof Migrator102_103)) {
			MigrationUtil.formatValue(e);
		}
	}
	
	protected void initMigrate() {		
	}
	
	protected void migrateDiagram(IProgressMonitor monitor) throws Exception {	
	}

}
