//------------------------------------------------------------------------------
// 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.edit.validation;

import java.util.Collection;
import java.util.Iterator;

import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.provider.AdapterFactoryTreeIterator;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.LibraryEditResources;
import org.eclipse.epf.library.edit.process.BSActivityItemProvider;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.library.edit.util.Suppression;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.DescribableElement;
import org.eclipse.epf.uma.NamedElement;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.TeamProfile;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.osgi.util.NLS;

/**
 * This class defines various static methods to validate name of specified
 * object
 * 
 * @author Phong Nguyen Le
 * @since 1.0
 */
public final class NameChecker {

	private static final String ELEMENT_TEXT = LibraryEditResources.element_text; //$NON-NLS-1$
	
	private static final INameProvider presentationNameProvider = new INameProvider() {

		public String getName(Object object) {
			if(object instanceof BreakdownElement) {
				return ProcessUtil.getPresentationName((BreakdownElement) object);
			}
			else if(object instanceof DescribableElement) {
				return ((DescribableElement)object).getPresentationName();
			}
			return null;
		}
		
	};
	
	private static String checkName(AdapterFactory adapterFactory,
			Object parent, Object e, final Class type,
			INameProvider nameProvider, String newName, Suppression suppresion,
			boolean ignoreSuppressed) {
		IFilter childFilter = new IFilter() {

			public boolean accept(Object obj) {
				return type.isInstance(obj);
			}

		};

		return checkName(adapterFactory, parent, e, childFilter, nameProvider,
				newName, suppresion, ignoreSuppressed);
	}

	private static String checkName(AdapterFactory adapterFactory,
			Object parent, Object e, IFilter childFilter,
			EStructuralFeature nameFeature, String newName,
			Suppression suppression, boolean ignoreSuppressed) {
		return checkName(adapterFactory, parent, e, childFilter,
				createNameProvider(nameFeature), newName, suppression,
				ignoreSuppressed);
	}

	private static String checkName(AdapterFactory adapterFactory,
			Object parent, Object e, IFilter childFilter,
			INameProvider nameProvider, String newName,
			Suppression suppression, boolean ignoreSuppressed) 
	{
		if (ignoreSuppressed)
			if (suppression != null && suppression.isSuppressed(e)) {
				return null;
			}

		ITreeItemContentProvider adapter = (ITreeItemContentProvider) adapterFactory
				.adapt(parent, ITreeItemContentProvider.class);
		Collection children;

		// get children of the rolled-down dapter
		//
		boolean wasRolledUp = false;
		BSActivityItemProvider bsItemProvider = null;
		if (adapter instanceof BSActivityItemProvider) {
			bsItemProvider = ((BSActivityItemProvider) adapter);
			wasRolledUp = bsItemProvider.isRolledUp();
		}
		try {
			if (wasRolledUp) {
				bsItemProvider.setRolledUp(false);
			}
			children = adapter.getChildren(parent);
		} catch (NullPointerException ex) {
			throw ex;
		} finally {
			if (wasRolledUp) {
				bsItemProvider.basicSetRolledUp(wasRolledUp);
			}
		}

		for (Iterator iter = children.iterator(); iter.hasNext();) {
			Object item = iter.next();

			// skip checking on suppressed element
			//
/*170058	if (suppression != null && suppression.isSuppressed(item)) {
				continue;
			}*/

			Object child = TngUtil.unwrap(item);
			if (child != e && childFilter.accept(child)) {
				String name = nameProvider.getName(child);
				if (name.equalsIgnoreCase(newName)) {
					// return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
					return NLS.bind(
							LibraryEditResources.duplicateElementNameError_msg,
							name);
				}
			}
		}
		return null;
	}

	private static INameProvider createNameProvider(
			final EStructuralFeature nameFeature) {
		if(nameFeature == UmaPackage.eINSTANCE
								.getDescribableElement_PresentationName()) {
			return presentationNameProvider; 
		}
		
		return new INameProvider() {

			public String getName(Object object) {
				if (object instanceof EObject) {
					return (String) ((EObject) object).eGet(nameFeature);
				} else {
					return null;
				}
			}

		};
	}

	public static String checkName(AdapterFactory adapterFactory,
			final BreakdownElement e, Class type, EStructuralFeature nameFeature,
			String newName, Suppression suppression) 
	{
		return checkName(adapterFactory, null, e, type, nameFeature, newName,
				suppression, false);
	}
	
	public static String checkName(AdapterFactory adapterFactory, Object parent,
			final BreakdownElement e, Class type, final EStructuralFeature nameFeature,
			String newName, Suppression suppression, boolean ignoreSuppressed) 
	{
		String msg = checkEmpty(e, newName);
		if(msg != null) {
			return msg;
		}

		if(type == null) {
			type = chooseType(e);
		}
		
		if(parent == null) {
			ITreeItemContentProvider itemProvider = (ITreeItemContentProvider) adapterFactory
					.adapt(e, ITreeItemContentProvider.class);
			parent = itemProvider.getParent(e);
			if(parent == null) {
				return null;
			}
		}

		// basic check
		//
		msg = checkName(adapterFactory, parent, e, type,
				createNameProvider(nameFeature), newName, suppression,
				ignoreSuppressed);

		if (msg != null)
			return msg;
		IFilter childFilter = null;
		if (e instanceof TeamProfile) {
			// don't allow team with the same name within the same scope
			//
			childFilter = new IFilter() {
				public boolean accept(Object obj) {
					return e instanceof TeamProfile;
				}
			};
		}

		// PLEASE DON'T CLEAN UP.
		// Commented out for now, since we change scope of Deliverable.
		// else if (e instanceof WorkProductDescriptor
		// && ((WorkProductDescriptor) e).getWorkProduct() instanceof
		// Deliverable) {
		// childFilter = new IFilter() {
		//	
		// public boolean accept(Object obj) {
		// return e instanceof WorkProductDescriptor
		// && ((WorkProductDescriptor) e).getWorkProduct() instanceof
		// Deliverable;
		// }
		// };
		// }

		if (childFilter != null) {
			return checkNameInScope(adapterFactory, parent, e, nameFeature, newName,
					childFilter, suppression, ignoreSuppressed);
		}

		return null;
	}
	
	private static String checkEmpty(Object e, String newName) {
		String elementType;
		if (e instanceof NamedElement) {
			elementType = TngUtil.getTypeText((NamedElement) e);
		} else {
			elementType = ELEMENT_TEXT;
		}
		if (newName == null || newName.trim().length() == 0) {			
			return NLS.bind(LibraryEditResources.emptyElementNameError_msg,
					StrUtil.toLower(elementType));
		}
		return null;
	}

	/**
	 * Used by
	 * {@link #checkName(AdapterFactory, BreakdownElement, EStructuralFeature, String, Suppression, boolean) checkName()}
	 * 
	 * @param e
	 * @return
	 */
	private static Class chooseType(BreakdownElement e) {
		if (e instanceof Activity) {
			return Activity.class;
		} else if (e instanceof TaskDescriptor) {
			return TaskDescriptor.class;
		} else if (e instanceof RoleDescriptor) {
			return RoleDescriptor.class;
		} else if (e instanceof WorkProductDescriptor) {
			return WorkProductDescriptor.class;
		} else {
			return e.getClass();
		}
		// return BreakdownElement.class;
	}

	private static String checkNameInScope(AdapterFactory adapterFactory,
			Object currentParent, BreakdownElement e,
			EStructuralFeature feature, String name, IFilter childFilter,
			Suppression suppression, boolean ignoreSuppressed) {
		// check up
		for (Object parent = currentParent; parent != null;) {
			String msg = checkName(adapterFactory, parent, e, childFilter,
					feature, name, suppression, ignoreSuppressed);
			if (msg != null)
				return msg;
			ITreeItemContentProvider itemProvider = (ITreeItemContentProvider) adapterFactory
					.adapt(parent, ITreeItemContentProvider.class);
			parent = itemProvider.getParent(parent);
		}

		// check down
		if (currentParent != null) {
			Iterator iter = new AdapterFactoryTreeIterator(adapterFactory,
					currentParent, false);
			while (iter.hasNext()) {
				Object child = TngUtil.unwrap(iter.next());
				if (child != e && childFilter.accept(child)) {
					String childName = (String) ((EObject) child).eGet(feature);
					if (name.equalsIgnoreCase(childName)) {
						// return I18nUtil.formatString(RESOURCE_BUNDLE, key,
						// data);
						return NLS
								.bind(
										LibraryEditResources.duplicateElementNameError_msg,
										name);
					}

				}
			}
		}

		return null;
	}

	public static String checkName(AdapterFactory adapterFactory,
			final BreakdownElement e, EStructuralFeature feature, String name,
			Suppression suppression) {
		return checkName(adapterFactory, e, feature, name, suppression, false);
	}

	/**
	 * Checks the name or presentation name of a breakdown element that is
	 * already part of a process.
	 * 
	 * @param adapterFactory
	 * @param e
	 * @param feature
	 * @param name
	 * @param suppression
	 * @param ignoreSuppressed
	 * @return
	 */
	public static String checkName(AdapterFactory adapterFactory,
			final BreakdownElement e, EStructuralFeature feature, String name,
			Suppression suppression, boolean ignoreSuppressed) 
	{
		return checkName(adapterFactory, (Object)null, e, (Class)null, feature, name, suppression, ignoreSuppressed);
	}
	
	public static boolean canHaveEmptyPresentationName(DescribableElement e) {
		if(e instanceof VariabilityElement) {
			VariabilityType vType = ((VariabilityElement)e).getVariabilityType();
			return vType == VariabilityType.EXTENDS_LITERAL
				|| vType == VariabilityType.CONTRIBUTES_LITERAL
				|| vType == VariabilityType.LOCAL_CONTRIBUTION_LITERAL;			
		}
		return false;	
	}
}
