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

import java.io.File;
import java.util.Iterator;
import java.util.List;

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.ITreeItemContentProvider;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.LibraryEditResources;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.edit.validation.IValidator;
import org.eclipse.epf.library.edit.validation.IValidatorFactory;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.ContentPackage;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.DescribableElement;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.NamedElement;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.osgi.util.NLS;


/**
 * @author Phong Nguyen Le - Aug 4, 2005
 * @since 1.0
 */
public class ValidatorFactory implements IValidatorFactory {
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.library.edit.validation.IValidatorFactory#createNameValidator(org.eclipse.epf.uma.ContentElement)
	 */
	public IValidator createNameValidator(Object parent, ContentElement e) {
		if (parent instanceof CustomCategory && e instanceof CustomCategory) {
			return new ContentElementNameValidator((EObject) parent,
					UmaPackage.eINSTANCE
							.getCustomCategory_CategorizedElements(), e,
					new TypeFilter(e));
		}
		EObject container = null;
		if (parent instanceof EObject) {
			container = (EObject) parent;
		}
		return new ContentElementNameValidator(container, e, new TypeFilter(e));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.library.edit.validation.IValidatorFactory#createPresentationNameValidator(org.eclipse.epf.uma.ContentElement)
	 *      Changed from ContentElement to DescribableElement, because
	 *      PresentationName attribute is available in DescribableElement.
	 */
	public IValidator createPresentationNameValidator(Object parent,
			DescribableElement e) {
		// if(parent instanceof EObject) {
		// return new UniquenessValidator((EObject) parent, null, new
		// TypeFilter(e), e,
		// UmaPackage.eINSTANCE.getDescribableElement_PresentationName(),
		// "presentation name");
		// }
		if (e instanceof BreakdownElement && parent instanceof Process) {
			final Object parentx = parent;
			return new IValidator() {

				public String isValid(String newText) {
					Process localparent = ((Process) parentx);
					List list = localparent.getBreakdownElements();
					for (Iterator itor = list.iterator(); itor.hasNext();) {
						BreakdownElement element = (BreakdownElement) itor
								.next();
						if (element.getPresentationName().equals(newText)) {
							//		return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
							return NLS.bind(LibraryEditResources.duplicateElementNameError_msg, newText);
						}
					}
					return null;
				}

			};
		}
		if (e instanceof BreakdownElement && parent instanceof Activity) {
			final Object parentx = parent;
			return new IValidator() {
				public String isValid(String newText) {
					Activity localparent = ((Activity) parentx);
					List list = localparent.getBreakdownElements();
					for (Iterator itor = list.iterator(); itor.hasNext();) {
						BreakdownElement element = (BreakdownElement) itor
								.next();
						if (element.getPresentationName().equals(newText)) {
							//		return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
							return NLS.bind(LibraryEditResources.duplicateElementNameError_msg, newText);
						}
					}
					return null;
				}

			};
		}
		return DoNothingValidator.INSTANCE;
	}

	public static class TypeFilter implements IFilter {
		private int classID;

		/**
		 * 
		 */
		public TypeFilter(EObject obj) {
			classID = obj.eClass().getClassifierID();
		}

		public boolean accept(Object obj) {
			return obj instanceof EObject
					&& classID == ((EObject) obj).eClass().getClassifierID();
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.library.edit.validation.IValidatorFactory#createNameValidator(org.eclipse.epf.uma.NamedElement)
	 */
	public IValidator createNameValidator(Object parent, final NamedElement e) {
		if (e instanceof ContentElement) {
			return createNameValidator(parent, (ContentElement) e);
		} else if (e instanceof ProcessComponent
				&& parent instanceof ProcessPackage) {
			return new ProcessComponentNameValidator((ProcessPackage) parent,
					(ProcessComponent) e);
		} else if ((e instanceof ContentPackage && parent instanceof ContentPackage) ||
				(e instanceof ProcessPackage && parent instanceof ProcessPackage)) {
			return new UniquenessValidator((EObject) parent,
					UmaPackage.eINSTANCE.getMethodPackage_ChildPackages(),
					new TypeFilter(e), e, UmaPackage.eINSTANCE
							.getNamedElement_Name(), "name"); //$NON-NLS-1$
		} else if (parent instanceof MethodLibrary) {			
			final MethodLibrary lib = (MethodLibrary) parent;
			if(e == null || e instanceof MethodPlugin) {
				return new IValidator() {

					public String isValid(String newText) {
						File dir = new File(lib.eResource().getURI().toFileString())
						.getParentFile();
						String elementTypeText = (e != null) ? TngUtil
								.getTypeText(e) : TngUtil
								.getTypeText("MethodPlugin"); //$NON-NLS-1$
								return TngUtil.checkName(dir, lib.getMethodPlugins(), e,
										newText, elementTypeText, true);
					}

				};
			}
			else if(e instanceof MethodConfiguration) {
				return new MethodConfigurationNameValidator(lib, (MethodConfiguration) e);
			}
		} else if (e instanceof BreakdownElement && parent instanceof Process
				|| parent instanceof ProcessComponent) {
			final Object parentx = parent;
			return new IValidator() {

				public String isValid(String newText) {
					Process localparent = ((Process) parentx);
					List list = localparent.getBreakdownElements();
					for (Iterator itor = list.iterator(); itor.hasNext();) {
						BreakdownElement element = (BreakdownElement) itor
								.next();
						if (element.getPresentationName().equals(newText)) {
							//		return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
							return NLS.bind(LibraryEditResources.duplicateElementNameError_msg, newText); 
						}
					}
					return null;
					// return
					// (TngUtil.checkWorkBreakdownElementPresentationName(e,
					// e.getName()));
				}

			};

		}

		return DoNothingValidator.INSTANCE;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.library.edit.validation.IValidatorFactory#createNameValidator(org.eclipse.epf.uma.NamedElement,
	 *      org.eclipse.emf.common.notify.AdapterFactory)
	 */
	public IValidator createNameValidator(NamedElement e,
			AdapterFactory adapterFactory) {
		EStructuralFeature containingFeature = TngUtil.getContainingFeature(e,
				adapterFactory);
		if (containingFeature != null) {
			EObject parent = (EObject) ((ITreeItemContentProvider) adapterFactory
					.adapt(e, ITreeItemContentProvider.class)).getParent(e);
			if (e instanceof ContentElement) {
				return new ContentElementNameValidator(parent,
						containingFeature, (ContentElement) e,
						new TypeFilter(e));
			} else if (e instanceof ProcessComponent
					&& parent instanceof ProcessPackage) {
				return new ProcessComponentNameValidator(
						(ProcessPackage) parent, (ProcessComponent) e);
			} else {
				return new UniquenessValidator(parent, containingFeature,
						new TypeFilter(e), e, UmaPackage.eINSTANCE
								.getNamedElement_Name(), "name"); //$NON-NLS-1$
			}
		}
		return createNameValidator(e.eContainer(), e);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.edit.validation.IValidatorFactory#createValidator(org.eclipse.emf.ecore.EObject, org.eclipse.emf.ecore.EStructuralFeature, java.lang.Object)
	 */
	public IValidator createValidator(EObject object, EStructuralFeature feature, Object value) {
		throw new UnsupportedOperationException("No implemented yet"); //$NON-NLS-1$
	};

}