//------------------------------------------------------------------------------
// 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.authoring.ui.util;

import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IMarker;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.epf.authoring.ui.AuthoringUIPlugin;
import org.eclipse.epf.authoring.ui.AuthoringUIResources;
import org.eclipse.epf.authoring.ui.views.LibraryView;
import org.eclipse.epf.persistence.MultiFileSaveUtil;
import org.eclipse.epf.persistence.refresh.RefreshJob;
import org.eclipse.epf.persistence.util.UnresolvedProxyMarkerManager;
import org.eclipse.epf.uma.ContentDescription;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.ContentPackage;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.util.ContentDescriptionFactory;
import org.eclipse.epf.uma.util.IMethodLibraryPersister;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.IMarkerResolutionGenerator;

/**
 * @author Phong Nguyen Le - Jul 25, 2006
 * @since  1.0
 */
public class MarkerResolutionGenerator implements IMarkerResolutionGenerator {
	private static final IMarkerResolution[] EMPTY_RESOLUTIONS = new IMarkerResolution[0];
	
	private static class ShowOwnerInLibraryView implements IMarkerResolution {

		private Object owner;

		/**
		 * @param owner
		 */
		private ShowOwnerInLibraryView(Object owner) {
			super();
			this.owner = owner;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.ui.IMarkerResolution#getLabel()
		 */
		public String getLabel() {
			return AuthoringUIResources.MarkerResolutionGenerator_showOwnerInLibraryView;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.ui.IMarkerResolution#run(org.eclipse.core.resources.IMarker)
		 */
		public void run(IMarker marker) {
			LibraryView.getView().setSelectionToViewer(owner);
		}
		
	}
	
	private static class MarkerResolution implements IMarkerResolution {
		private EObject owner;
		private EReference reference;
		private int index;
				
		private MarkerResolution(EObject owner, EReference ref, int index) {
			super();
			this.owner = owner;
			this.reference = ref;
			this.index = index;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.ui.IMarkerResolution#getLabel()
		 */
		public String getLabel() {
			return AuthoringUIResources.MarkerResolutionGenerator_removeUnresolvedReference;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.ui.IMarkerResolution#run(org.eclipse.core.resources.IMarker)
		 */
		public void run(IMarker marker) {
			if(reference.isMany()) {
				((List)owner.eGet(reference)).remove(index);
			}
			else {
				owner.eSet(reference, null);
			}
			IMethodLibraryPersister.FailSafeMethodLibraryPersister persister = ContentDescriptionFactory.getMethodLibraryPersister().getFailSafePersister();
			try {
				persister.save(owner.eResource());
				persister.commit();
			}
			catch(Exception e) {
				AuthoringUIPlugin.getDefault().getLogger().logError(e);
				persister.rollback();
			}
		}
		
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.IMarkerResolutionGenerator#getResolutions(org.eclipse.core.resources.IMarker)
	 */
	public IMarkerResolution[] getResolutions(IMarker marker) {
		// The only resolution we provide right now is removing the unresolving proxy
		//
		try {
			String proxyURI = (String) marker.getAttribute(UnresolvedProxyMarkerManager.PROXY_URI);
			String ownerGUID = (String) marker.getAttribute(UnresolvedProxyMarkerManager.OWNER_GUID);
			if(proxyURI != null && ownerGUID != null) {
				Resource resource = RefreshJob.getInstance().getResource(marker.getResource());
				if(resource != null) {
					EObject owner = resource.getEObject(ownerGUID);
					if(owner != null) {
						URI uri = URI.createURI(proxyURI);
						// find the proxy
						//
						int index = -1;
						EReference reference = null;
						find_proxy_loop:
						for (Iterator iter = owner.eClass().getEAllReferences().iterator(); iter
								.hasNext();) {
							EReference ref = (EReference) iter.next();
							if(ref.isChangeable() && !ref.isDerived()) {
								if(ref.isMany()) {
									InternalEList list = (InternalEList) owner.eGet(ref);
									int id = 0;
									for (Iterator iterator = list.basicIterator(); iterator
											.hasNext();) {
										InternalEObject o = (InternalEObject) iterator.next();
										if(o.eIsProxy() && uri.equals(o.eProxyURI())) {
											index = id;
											reference = ref;
											break find_proxy_loop;
										}
										id++;
									}
								}
								else {
									InternalEObject o = (InternalEObject) owner.eGet(ref, false);
									if(o != null && o.eIsProxy() && uri.equals(o.eProxyURI())) {
										reference = ref;
										break find_proxy_loop;
									}
								}
							}
						}
						if(reference != null) {
							Object selectableOwner = getSelectableObject(owner);
							if(selectableOwner != null) {
								return new IMarkerResolution[] {
										new MarkerResolution(owner, reference, index),
										new ShowOwnerInLibraryView(selectableOwner)
								};
							}
							else {
								return new IMarkerResolution[] {
										new MarkerResolution(owner, reference, index),
								};
							}
						}
					}
				}
			}
		} catch (Exception e) {
			AuthoringUIPlugin.getDefault().getLogger().logError(e);
		}
		return EMPTY_RESOLUTIONS;
	}

	/**
	 * @param owner
	 * @return
	 */
	private static Object getSelectableObject(EObject owner) {
		if(owner instanceof MethodPlugin || owner instanceof ContentElement || owner instanceof ContentPackage 
				|| owner instanceof ProcessComponent) {
			return owner;
		}
		if(owner instanceof MethodElement) {
			ProcessComponent procComp = UmaUtil.getProcessComponent((MethodElement) owner);
			if(procComp != null) {
				return procComp;
			}
		}
		if(owner instanceof ProcessPackage) {
			return owner;
		}
		if(owner instanceof ContentDescription && owner.eContainer() instanceof ContentElement) {
			return owner.eContainer(); 
		}
		Resource resource = owner.eResource();
		MethodElement e = MultiFileSaveUtil.getMethodElement(resource);
		if(e != owner) {
			return getSelectableObject(e);
		}
		return null;
	}

}
