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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.IDisposable;
import org.eclipse.epf.library.edit.IConfigurable;
import org.eclipse.epf.library.edit.IConfigurator;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.IGroupContainer;
import org.eclipse.epf.library.edit.IStatefulItemProvider;
import org.eclipse.epf.library.edit.LibraryEditPlugin;
import org.eclipse.epf.library.edit.category.DisciplineCategoriesItemProvider;
import org.eclipse.epf.library.edit.category.RoleSetsItemProvider;
import org.eclipse.epf.library.edit.util.ModelStructure;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.ContentCategory;
import org.eclipse.epf.uma.Domain;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.Role;
import org.eclipse.epf.uma.Task;
import org.eclipse.epf.uma.Tool;
import org.eclipse.epf.uma.ToolMentor;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductType;
import org.eclipse.epf.uma.util.AssociationHelper;

/**
 * The item provider adapter for a method configuration in the Configuration
 * view.
 * 
 * @author Phong Nguyen Le
 * @author Shilpa Toraskar
 * @author Kelvin Low
 * @since 1.0
 */
public class MethodConfigurationItemProvider extends
		org.eclipse.epf.uma.provider.MethodConfigurationItemProvider implements
		IGroupContainer, IConfigurable, IStatefulItemProvider {

	private Map groupItemProviderMap;

	// changed to protected, extended class can play with children variable.
	protected ArrayList children;

	private static final IFilter disciplinesFilter = new IFilter() {

		public boolean accept(Object obj) {
			ContentCategory element = (ContentCategory) obj;
			// RATLC00381835 - Browsing: With categories, replace generalization
			// causes both replacement and base to become invisible to browsing
			return DisciplineCategoriesItemProvider.accept(element) /*
																	 * &&
																	 * element.getVariabilityBasedOnElement() ==
																	 * null
																	 */;
		}
	};

	private static final IFilter domainFilter = new IFilter() {

		public boolean accept(Object obj) {
			// RATLC00381835 - Browsing: With categories, replace generalization
			// causes both replacement and base to become invisible to browsing
			return obj instanceof Domain /*
											 * &&
											 * ((Domain)obj).getVariabilityBasedOnElement() ==
											 * null
											 */;
		}

	};

	private static final IFilter workProductTypesFilter = new IFilter() {

		public boolean accept(Object obj) {
			// RATLC00381835 - Browsing: With categories, replace generalization
			// causes both replacement and base to become invisible to browsing
			return obj instanceof WorkProductType /*
													 * &&
													 * ((WorkProductType)obj).getVariabilityBasedOnElement() ==
													 * null
													 */;
		}

	};

	private static final IFilter roleSetsFilter = new IFilter() {

		public boolean accept(Object obj) {
			// RATLC00381835 - Browsing: With categories, replace generalization
			// causes both replacement and base to become invisible to browsing
			return RoleSetsItemProvider.accept(obj) /*
													 * &&
													 * ((VariabilityElement)obj).getVariabilityBasedOnElement() ==
													 * null
													 */;
		}
	};

	private static final IFilter toolsFilter = new IFilter() {

		public boolean accept(Object obj) {
			// RATLC00381835 - Browsing: With categories, replace generalization
			// causes both replacement and base to become invisible to browsing
			return obj instanceof Tool /*
										 * &&
										 * ((Tool)obj).getVariabilityBasedOnElement() ==
										 * null
										 */;
		}

	};

	private static final IFilter customCategoriesFilter = new IFilter() {

		public boolean accept(Object obj) {
			// RATLC00381835 - Browsing: With categories, replace generalization
			// causes both replacement and base to become invisible to browsing
			return org.eclipse.epf.library.edit.category.CustomCategoriesItemProvider
					.accept(obj) /*
									 * &&
									 * ((VariabilityElement)obj).getVariabilityBasedOnElement() ==
									 * null
									 */;
		}

	};

	private static final IFilter uncategorizedTaskFilter = new IFilter() {

		public boolean accept(Object obj) {
			return obj instanceof Task
					&& AssociationHelper.getDisciplines((Task) obj).isEmpty();
		}

	};

	private static final IFilter domainUncategorizedWorkProductFilter = new IFilter() {

		public boolean accept(Object obj) {
			return obj instanceof WorkProduct
					&& AssociationHelper.getDomain((WorkProduct) obj) == null;
		}

	};

	private static final IFilter wpTypeUncategorizedWorkProductFilter = new IFilter() {

		public boolean accept(Object obj) {
			return obj instanceof WorkProduct
					&& AssociationHelper.getWorkProductTypes((WorkProduct) obj)
							.isEmpty();
		}

	};

	private static final IFilter uncategorizedRoleFilter = new IFilter() {

		public boolean accept(Object obj) {
			return obj instanceof Role
					&& AssociationHelper.getRoleSets((Role) obj).isEmpty();
		}

	};

	private static final IFilter uncategorizedToolMentorFilter = new IFilter() {
		public boolean accept(Object obj) {
			return obj instanceof ToolMentor
					&& AssociationHelper.getTool((ToolMentor) obj) == null;
		}

	};

	private IConfigurator configurator;

	private IFilter filter;

	/**
	 * Creates a new instance.
	 */
	public MethodConfigurationItemProvider(AdapterFactory adapterFactory) {
		super(adapterFactory);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.edit.provider.ItemProviderAdapter#dispose()
	 */
	public void dispose() {
		if (groupItemProviderMap != null) {
			for (Iterator iter = groupItemProviderMap.values().iterator(); iter
					.hasNext();) {
				Object adapter = iter.next();
				if (adapter instanceof IDisposable) {
					((IDisposable) adapter).dispose();
				}
			}
			groupItemProviderMap.clear();
			groupItemProviderMap = null;
		}

		if (children != null) {
			children.clear();
			children = null;
		}

		super.dispose();
	}

	public Collection getChildren(Object object) {
		// if(object instanceof MethodConfiguration) {
		// return Collections.singleton(new
		// ObjectLinkItemProvider(adapterFactory, object, (Notifier) object));
		// }
		// MethodConfiguration conf = (MethodConfiguration)
		// ((ObjectLinkItemProvider) object).getLinkedObject();
		MethodConfiguration conf = (MethodConfiguration) object;
		if (children == null) {
			children = new ArrayList();
			groupItemProviderMap = new HashMap();
			String name;
			Object uncategorizedImage;
			CategoriesItemProvider child;

			name = LibraryEditPlugin.INSTANCE
					.getString("_UI_Disciplines_group"); //$NON-NLS-1$
			child = new CategoriesItemProvider(
					adapterFactory,
					conf,
					name,
					LibraryEditPlugin.INSTANCE.getImage("full/obj16/Tasks_cfv"), //$NON-NLS-1$
					ModelStructure.DEFAULT.disciplineDefinitionPath);
			child.setParent(conf);
			child.setUncategorizedFilter(uncategorizedTaskFilter);
			child.setCategorizedFilter(disciplinesFilter);
			child.setUncategorizedLabel(LibraryEditPlugin.INSTANCE
					.getString("_UI_Uncategorized_Tasks_text")); //$NON-NLS-1$
			uncategorizedImage = LibraryEditPlugin.INSTANCE
					.getImage("full/obj16/Tasks"); //$NON-NLS-1$
			child.setUncategorizedImage(uncategorizedImage);
			children.add(child);
			groupItemProviderMap.put(name, child);

			name = LibraryEditPlugin.INSTANCE.getString("_UI_Domains_group"); //$NON-NLS-1$
			child = new CategoriesItemProvider(adapterFactory, conf, name,
					LibraryEditPlugin.INSTANCE.getImage("full/obj16/Domains"), //$NON-NLS-1$
					ModelStructure.DEFAULT.domainPath);
			child.setParent(conf);
			child.setUncategorizedFilter(domainUncategorizedWorkProductFilter);
			uncategorizedImage = LibraryEditPlugin.INSTANCE
					.getImage("full/obj16/WorkProducts"); //$NON-NLS-1$
			child.setUncategorizedImage(uncategorizedImage);
			child.setCategorizedFilter(domainFilter);
			children.add(child);
			groupItemProviderMap.put(name, child);

			name = LibraryEditPlugin.INSTANCE
					.getString("_UI_WorkProductTypes_group"); //$NON-NLS-1$
			child = new WorkProductTypesItemProvider(adapterFactory, conf,
					name, LibraryEditPlugin.INSTANCE
							.getImage("full/obj16/WorkProducts"), //$NON-NLS-1$
					ModelStructure.DEFAULT.workProductTypePath);
			child.setParent(conf);
			child.setUncategorizedFilter(wpTypeUncategorizedWorkProductFilter);
			uncategorizedImage = LibraryEditPlugin.INSTANCE
					.getImage("full/obj16/WorkProducts"); //$NON-NLS-1$
			child.setUncategorizedImage(uncategorizedImage);
			child.setCategorizedFilter(workProductTypesFilter);
			children.add(child);
			groupItemProviderMap.put(name, child);

			name = LibraryEditPlugin.INSTANCE.getString("_UI_Role_Sets_group"); //$NON-NLS-1$
			child = new CategoriesItemProvider(adapterFactory, conf, name,
					LibraryEditPlugin.INSTANCE.getImage("full/obj16/Roles"), //$NON-NLS-1$
					ModelStructure.DEFAULT.roleSetPath);
			child.setParent(conf);
			child.setUncategorizedFilter(uncategorizedRoleFilter);
			child.setCategorizedFilter(roleSetsFilter);
			child.setUncategorizedLabel(LibraryEditPlugin.INSTANCE
					.getString("_UI_Uncategorized_Roles_text")); //$NON-NLS-1$
			uncategorizedImage = LibraryEditPlugin.INSTANCE
					.getImage("full/obj16/Roles"); //$NON-NLS-1$
			child.setUncategorizedImage(uncategorizedImage);
			children.add(child);
			groupItemProviderMap.put(name, child);

			name = LibraryEditPlugin.INSTANCE.getString("_UI_Tools_group"); //$NON-NLS-1$
			child = new CategoriesItemProvider(adapterFactory, conf, name,
					LibraryEditPlugin.INSTANCE.getImage("full/obj16/Tools"), //$NON-NLS-1$
					ModelStructure.DEFAULT.toolPath);
			child.setParent(conf);
			child.setCategorizedFilter(toolsFilter);
			child.setUncategorizedFilter(uncategorizedToolMentorFilter);
			uncategorizedImage = LibraryEditPlugin.INSTANCE
					.getImage("full/obj16/Tools"); //$NON-NLS-1$
			child.setUncategorizedImage(uncategorizedImage);
			children.add(child);
			groupItemProviderMap.put(name, child);

			name = LibraryEditPlugin.INSTANCE.getString("_UI_Processes_group"); //$NON-NLS-1$
			Object otherChild = new ProcessesItemProvider(adapterFactory, conf,
					ModelStructure.DEFAULT);
			children.add(otherChild);
			groupItemProviderMap.put(name, otherChild);

			name = LibraryEditPlugin.INSTANCE
					.getString("_UI_Custom_Categories_group"); //$NON-NLS-1$
			child = new CategoriesItemProvider(adapterFactory, conf, name,
					LibraryEditPlugin.INSTANCE
							.getImage("full/obj16/MethodPackages"), //$NON-NLS-1$
					ModelStructure.DEFAULT.customCategoryPath);
			child.setParent(conf);
			child.setCategorizedFilter(customCategoriesFilter);
			children.add(child);
			groupItemProviderMap.put(name, child);

			name = LibraryEditPlugin.INSTANCE.getString("_UI_Guidances_group"); //$NON-NLS-1$
			GuidanceGroupingItemProvider child1 = new GuidanceGroupingItemProvider(
					adapterFactory, conf);
			child1.setFilter(filter);
			children.add(child1);
			groupItemProviderMap.put(name, child1);
		}

		return children;
	}

	// /* (non-Javadoc)
	// * @see
	// org.eclipse.emf.edit.provider.ItemProviderAdapter#getElements(java.lang.Object)
	// */
	// public Collection getElements(Object object) {
	// return Collections.singleton(object);
	// }
	//    
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.edit.provider.ItemProviderAdapter#hasChildren(java.lang.Object)
	 */
	public boolean hasChildren(Object object) {
		return super.hasChildren(object);
	}

	public String getText(Object object) {
		return TngUtil.getLabel(object,
				getString("_UI_MethodConfiguration_type")); //$NON-NLS-1$
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.IGroupContainer#getGroupItemProvider(java.lang.String)
	 */
	public Object getGroupItemProvider(String name) {
		return groupItemProviderMap.get(name);
	}

	public Collection getNewChildDescriptors(Object object,
			EditingDomain editingDomain, Object sibling) {
		return Collections.EMPTY_LIST;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.IConfigurable#setFilter(com.ibm.library.edit.IFilter)
	 */
	public void setFilter(IFilter filter) {
		if (filter instanceof IConfigurator) {
			configurator = (IConfigurator) filter;
		}
		this.filter = filter;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.IConfigurable#setLabel(java.lang.String)
	 */
	public void setLabel(String label) {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.IConfigurable#setParent(java.lang.Object)
	 */
	public void setParent(Object parent) {
	}

	// public Object getParent(Object object) {
	// return plugin;
	// }

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.uma.provider.MethodConfigurationItemProvider#notifyChanged(org.eclipse.emf.common.notify.Notification)
	 */
	public void notifyChanged(Notification notification) {
		super.notifyChanged(notification);

		if (configurator != null) {
			switch (notification.getFeatureID(MethodConfiguration.class)) {
			case UmaPackage.METHOD_CONFIGURATION__METHOD_PLUGIN_SELECTION:
			case UmaPackage.METHOD_CONFIGURATION__METHOD_PACKAGE_SELECTION:
				configurator.notifyChanged(notification);
				break;
			}
		}
	}

}
