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

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.epf.authoring.ui.providers.CustomCategoryContentProvider;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;

/**
 * CheckboxTreeViewer wrapper that does not check parents when all children are checked.
 * 
 * @author Jeff Hardy
 *
 */
public class CustomCategoryTreeViewerWrapper extends
		GrayingCheckboxTreeViewerWrapper {
	
	protected List<Object> fUserCheckedStateStore= new ArrayList<Object>();
	
	protected Text textWidget;

	/**
	 * Creates a new instance.
	 */
	public CustomCategoryTreeViewerWrapper(Composite parent, int height,
			Object rootObject,
			AdapterFactoryContentProvider treeContentProvider,
			AdapterFactoryLabelProvider treeLabelProvider) {
		super (parent, height, rootObject, treeContentProvider, treeLabelProvider);
	}
	
	@Override
	protected boolean determineShouldBeWhiteChecked(Object treeElement) {
		return fUserCheckedStateStore.contains(treeElement);
	}
	
	protected boolean determineShouldBeAtLeastGrayChecked(Object treeElement) {
		// if any children of treeElement are still gray-checked then treeElement
		// must remain gray-checked as well
		Object[] children= getTreeChildren(treeElement);
		for (int i= 0; i < children.length; ++i) {
			if (fCheckedStateStore.contains(children[i]) || fUserCheckedStateStore.contains(children[i]))
				return true;
		}

		return false;
	}

		
	@Override
	protected void setTreeChecked(Object treeElement, boolean state) {
		if (state) {
			fUserCheckedStateStore.add(treeElement);
		} else
			fUserCheckedStateStore.remove(treeElement);
		
		super.setTreeChecked(treeElement, state);
	}

	/**
	 *	Iterates through the passed elements which are being realized for the first
	 *	time and check each one in the tree viewer as appropriate
	 */
//	@Override
//	protected void checkNewTreeElements(Object[] elements) {
//		for (int i= 0; i < elements.length; ++i) {
//			Object currentElement= elements[i];
//			boolean checked= fUserCheckedStateStore.contains(currentElement);
//			fTreeViewer.setChecked(currentElement, checked);
//			fTreeViewer.setGrayed(
//				currentElement,
//				checked && !fWhiteCheckedTreeItems.contains(currentElement));
//		}
//	}

	
	@Override
	protected void handleUpdateSelection(List items) {
		Iterator iterator= items.iterator();

		//Update the store before the hierarchy to prevent updating parents before all of the children are done
		while (iterator.hasNext()) {
			Object item= iterator.next();
			
			// if item is CC, find the FeatureValueWrapperItemProvider
			if (item instanceof CustomCategory) {
				item = getTreeItemForCC((CustomCategory)item);
			}
			
			//Replace the items in the checked state store with those from the supplied items
			if (!fUserCheckedStateStore.contains(item))
				fUserCheckedStateStore.add(item);
			if (!fCheckedStateStore.contains(item))
				fCheckedStateStore.add(item);
			// proceed up the tree element hierarchy
			Object parent= fTreeContentProvider.getParent(item);
			if (parent != null) {
				// if parent is CC, find the FeatureValueWrapperItemProvider
				if (parent instanceof CustomCategory) {
					parent = getTreeItemForCC((CustomCategory)parent);
				}
				addToHierarchyToCheckedStore(parent);
			}
		}

		//Now update hierarchies
		iterator= items.iterator();

		while (iterator.hasNext()) {
			Object item= iterator.next();
			// if item is CC, find the FeatureValueWrapperItemProvider
			if (item instanceof CustomCategory) {
				item = getTreeItemForCC((CustomCategory)item);
			}
			updateHierarchy(item);
		}
	}
	
	private Object getTreeItemForCC(CustomCategory cc) {
		if (fTreeContentProvider instanceof CustomCategoryContentProvider) {
			return ((CustomCategoryContentProvider)fTreeContentProvider).getTreeItemForCC(cc);
		} else {
			return cc;
		}
	}

	public Set<CustomCategory> getCheckedCustomCategories() {
		Set<CustomCategory> result = new HashSet<CustomCategory>();
		Set<Object> checkedItems = getWhiteCheckedTreeItems();
		for (Iterator<Object> iter = checkedItems.iterator();iter.hasNext();) {
			Object item = TngUtil.unwrap(iter.next());
			if (item instanceof CustomCategory) {
				result.add((CustomCategory)item);
			}
		}
		return result;
	}
	
	/**
	 *	Handles the selection of an item in the tree viewer
	 *
	 *	@param event ISelection
	 */
	public void selectionChanged(final SelectionChangedEvent event) {
		BusyIndicator.showWhile(getTree().getShell().getDisplay(), new Runnable() {
			public void run() {
				IStructuredSelection selection= (IStructuredSelection) event.getSelection();
				Object selectedElement= selection.getFirstElement();
				selectedElement = TngUtil.unwrap(selectedElement);
				if (selectedElement == null) {
					return;
				} else if (textWidget != null && selectedElement instanceof MethodElement) {
					// display selected element's description
					String briefDesc = ((MethodElement) selectedElement).getBriefDescription();
					textWidget.setText(briefDesc != null ? briefDesc : ""); //$NON-NLS-1$
				}
			}
		});
	}

	public void setTextWidget(Text textWidget) {
		this.textWidget = textWidget;
	}



}
