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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.CommandParameter;
import org.eclipse.emf.edit.command.CopyCommand.Helper;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.ILibraryItemProvider;
import org.eclipse.epf.library.edit.IStatefulItemProvider;
import org.eclipse.epf.library.edit.PresentationContext;
import org.eclipse.epf.library.edit.command.MethodElementAddCommand;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.ContentPackage;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.edit.command.MethodElementCreateCopyCommand;
import org.eclipse.epf.uma.edit.command.MethodElementInitializeCopyCommand;

/**
 * The item provider adapter for the "Content Packages" folder in the Library
 * view.
 * <p>
 * This class will be renamed as ContentPackagesItemProvider in EPF M5.
 * 
 * @author Phong Nguyen Le
 * @author Kelvin Low
 * @since 1.0
 */
public class ContentPackageItemProvider extends
		org.eclipse.epf.uma.provider.ContentPackageItemProvider implements
		IElementItemProvider, ILibraryItemProvider, IStatefulItemProvider {

	private RolesItemProvider roles;

	private TasksItemProvider tasks;

	private WorkProductsItemProvider workProducts;

	private GuidancesItemProvider guidances;

	private String label;

	private Object parent;

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

	/**
	 * @return Returns the roles.
	 */
	public RolesItemProvider getRoles() {
		return roles;
	}

	/**
	 * @return Returns the tasks.
	 */
	public TasksItemProvider getTasks() {
		return tasks;
	}

	/**
	 * @return Returns the workProducts.
	 */
	public WorkProductsItemProvider getWorkProducts() {
		return workProducts;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.edit.provider.ItemProviderAdapter#getChildrenFeatures(java.lang.Object)
	 */
	// public Collection getChildrenFeatures(Object object) {
	// if (childrenFeatures == null) {
	// childrenFeatures = new ArrayList();
	// childrenFeatures.add(UmaPackage.eINSTANCE.getMethodPackage_ChildPackages());
	// }
	// return childrenFeatures;
	// }
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.edit.provider.ItemProviderAdapter#getChildren(java.lang.Object)
	 */
	public Collection getChildren(Object object) {
		List allChildren = new ArrayList();
		ChildrenStore store = getChildrenStore(object);
		List result = null;
		if (store == null) {
			store = createChildrenStore(object);
			result = store != null ? null : new ArrayList();
			EObject eObject = (EObject) object;

			for (Iterator i = getChildrenFeatures(object).iterator(); i
					.hasNext();) {
				EStructuralFeature feature = (EStructuralFeature) i.next();
				if (feature.isMany()) {
					List children = (List) eObject.eGet(feature);
					List contentPkgs = new ArrayList();
					int index = 0;
					for (Iterator ci = children.iterator(); ci.hasNext(); index++) {
						Object child = ci.next();
						if (child instanceof ContentPackage) {
							child = wrap(eObject, feature, child, index);
							// if (store != null)
							// {
							// store.getList(feature).add(child);
							// }
							// else
							// {
							// result.add(child);
							// }
							contentPkgs.add(child);
						}
					}

					// sorting the content packages
					//
					Collections.sort(contentPkgs, PresentationContext.INSTANCE
							.getComparator());

					if (store != null) {
						store.getList(feature).addAll(contentPkgs);
					} else {
						result.addAll(contentPkgs);
					}
				} else {
					Object child = eObject.eGet(feature);
					if (child instanceof ContentPackage) {
						child = wrap(eObject, feature, child,
								CommandParameter.NO_INDEX);
						if (store != null) {
							store.setValue(feature, child);
						} else {
							result.add(child);
						}
					}
				}
			}
		}
		allChildren.addAll(store != null ? store.getChildren() : result);
		ContentPackage contentPkg = (ContentPackage) object;

		// remove old adapters (roles, tasks, workproducts) from the the
		// contentPkg
		//
		// EObject eObj = (EObject) object;
		if (roles == null) {
			// eObj.eAdapters().remove(roles);
			roles = new RolesItemProvider(adapterFactory, contentPkg);
		}
		if (tasks == null) {
			// eObj.eAdapters().remove(tasks);
			tasks = new TasksItemProvider(adapterFactory, contentPkg);
		}
		if (workProducts == null) {
			// eObj.eAdapters().remove(workProducts);
			workProducts = new WorkProductsItemProvider(adapterFactory,
					contentPkg);
		}
		if (guidances == null) {
			// eObj.eAdapters().remove(guidances);
			guidances = new GuidancesItemProvider(adapterFactory, contentPkg);
		}

		allChildren.add(roles);
		allChildren.add(tasks);
		allChildren.add(workProducts);
		allChildren.add(guidances);
		return allChildren;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.edit.provider.ItemProviderAdapter#collectNewChildDescriptors(java.util.Collection,
	 *      java.lang.Object)
	 */
	protected void collectNewChildDescriptors(Collection newChildDescriptors,
			Object object) {
		newChildDescriptors.add(createChildParameter(UmaPackage.eINSTANCE
				.getMethodPackage_ChildPackages(), UmaFactory.eINSTANCE
				.createContentPackage()));
	}

	// /* (non-Javadoc)
	// * @see
	// org.eclipse.emf.edit.provider.ItemProviderAdapter#createCommand(java.lang.Object,
	// org.eclipse.emf.edit.domain.EditingDomain, java.lang.Class,
	// org.eclipse.emf.edit.command.CommandParameter)
	// */
	// public Command createCommand(Object object, EditingDomain domain,
	// Class commandClass, CommandParameter commandParameter) {
	// // commandParameter.setOwner(((EObject)object).eContainer());
	// Command cmd = super.createCommand(object, domain, commandClass,
	// commandParameter);
	// System.out.println(getClass().getName() + "#createCommand: " +
	// commandClass + ", can execute: " + cmd.canExecute() + ", owner: " +
	// commandParameter.getOwner() + ", collection: " +
	// commandParameter.getCollection());
	// return cmd;
	// }

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.edit.provider.ItemProviderAdapter#getText(java.lang.Object)
	 */
	public String getText(Object object) {
		String txt;
		if (label != null) {
			txt = label;
		} else {
			txt = TngUtil
					.getLabel(object, getString("_UI_ContentPackage_type")); //$NON-NLS-1$
		}
		// check if the object has its own resource and it is modified to add
		// the dirty flag
		//
		Resource res = ((EObject) object).eResource();
		if (res != null && res.getContents().get(0) == object
				&& res.isModified()) {
			txt = txt + "*"; //$NON-NLS-1$
		}
		return txt;
	}

	private void setDefaultName(Object obj) {
		ContentPackage contentPackage = (ContentPackage) target;
		if (obj instanceof ContentPackage) {
			TngUtil.setDefaultName(contentPackage.getChildPackages(),
					(MethodElement) obj, "content_package"); //$NON-NLS-1$
		} else {
			TngUtil.setDefaultName(contentPackage.getChildPackages(),
					(MethodElement) obj, "method_package"); //$NON-NLS-1$
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.notify.Adapter#notifyChanged(org.eclipse.emf.common.notify.Notification)
	 */
	public void notifyChanged(Notification msg) {
		TngUtil.refreshParentIfNameChanged(msg, this);

		switch (msg.getFeatureID(ContentPackage.class)) {
		case UmaPackage.CONTENT_PACKAGE__CONTENT_ELEMENTS:
			return;
		case UmaPackage.CONTENT_PACKAGE__CHILD_PACKAGES:
			switch (msg.getEventType()) {
			case Notification.ADD:
				setDefaultName(msg.getNewValue());
				break;
			case Notification.ADD_MANY:
				for (Iterator iter = ((Collection) msg.getNewValue())
						.iterator(); iter.hasNext();) {
					setDefaultName(iter.next());
				}
				break;
			}
		}

		super.notifyChanged(msg);
	}

	/**
	 * @return
	 */
	public GuidancesItemProvider getGuidances() {
		return guidances;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.IConfigurable#setFilter(com.ibm.library.edit.IFilter)
	 */
	public void setFilter(IFilter filter) {
	}

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

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

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.edit.provider.ItemProviderAdapter#getParent(java.lang.Object)
	 */
	public Object getParent(Object object) {
		if (parent != null)
			return parent;
		return super.getParent(object);
	}

	// public Object getImage(Object object) {
	// return TngEditPlugin.INSTANCE.getImage("full/obj16/MethodPackages");
	// }

	protected Command createInitializeCopyCommand(EditingDomain domain,
			EObject owner, Helper helper) {
		return new MethodElementInitializeCopyCommand(domain, owner, helper);
	}

	protected Command createCreateCopyCommand(EditingDomain domain,
			EObject owner, Helper helper) {
		return new MethodElementCreateCopyCommand(domain, owner, helper);
	}

	protected Command createAddCommand(EditingDomain domain, EObject owner,
			EStructuralFeature feature, Collection collection, int index) {
		ArrayList selection = new ArrayList();
		for (Iterator iter = collection.iterator(); iter.hasNext();) {
			Object element = iter.next();

			// make sure that you cannot add MethodPackage that is not a
			// ContentPackage
			//
			if (element instanceof MethodPackage
					&& !(element instanceof ContentPackage)) {
				continue;
			}

			selection.add(element);
		}

		return new MethodElementAddCommand((AddCommand) super.createAddCommand(
				domain, owner, feature, selection, index));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.edit.provider.ItemProviderAdapter#dispose()
	 */
	public void dispose() {
		if (guidances != null) {
			guidances.dispose();
			guidances = null;
		}
		if (roles != null) {
			roles.dispose();
			roles = null;
		}
		if (tasks != null) {
			tasks.dispose();
			tasks = null;
		}
		if (workProducts != null) {
			workProducts.dispose();
			workProducts = null;
		}
		super.dispose();
	}

}
