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

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;

/**
 * Displays the searchable method elements, organized by types, in a tree view.
 * 
 * @author Kelvin Low
 * @since 1.0
 */
public class MethodSearchScopeViewer {

	private static final String ROOT = MethodSearchScope.ROOT;

	private static final String METHOD_CONTENT = MethodSearchScope.METHOD_CONTENT;

	private static final String ROLE = MethodSearchScope.ROLE;

	private static final String TASK = MethodSearchScope.TASK;

	private static final String WORK_PRODUCT = MethodSearchScope.WORK_PRODUCT;

	private static final String GUIDANCE = MethodSearchScope.GUIDANCE;

	private static final String CHECKLIST = MethodSearchScope.CHECKLIST;

	private static final String CONCEPT = MethodSearchScope.CONCEPT;

	private static final String ESTIMATION_CONSIDERATIONS = MethodSearchScope.ESTIMATION_CONSIDERATIONS;

	private static final String EXAMPLE = MethodSearchScope.EXAMPLE;

	private static final String GUIDELINE = MethodSearchScope.GUIDELINE;

	private static final String PRACTICE = MethodSearchScope.PRACTICE;

	private static final String REPORT = MethodSearchScope.REPORT;

	private static final String REUSABLE_ASSET = MethodSearchScope.REUSABLE_ASSET;

	private static final String ROADMAP = MethodSearchScope.ROADMAP;

	private static final String SUPPORTING_MATERIAL = MethodSearchScope.SUPPORTING_MATERIAL;

	private static final String TEMPLATE = MethodSearchScope.TEMPLATE;

	private static final String TERM_DEFINITION = MethodSearchScope.TERM_DEFINITION;

	private static final String TOOL_MENTOR = MethodSearchScope.TOOL_MENTOR;

	private static final String WHITEPAPER = MethodSearchScope.WHITEPAPER;

	private static final String STANDARD_CATEGORY = MethodSearchScope.STANDARD_CATEGORY;

	private static final String CUSTOM_CATEGORY = MethodSearchScope.CUSTOM_CATEGORY;

	private static final String PROCESS = MethodSearchScope.PROCESS;

	private static final String CAPABILITY_PATTERN = MethodSearchScope.CAPABILITY_PATTERN;

	private static final String DELIVERY_PROCESS = MethodSearchScope.DELIVERY_PROCESS;

	private static List rootList = new ArrayList();
	static {
		rootList.add(METHOD_CONTENT);
		rootList.add(PROCESS);
	}

	private static List methodContentList = new ArrayList();
	static {
		methodContentList.add(ROLE);
		methodContentList.add(TASK);
		methodContentList.add(WORK_PRODUCT);
		methodContentList.add(GUIDANCE);
		methodContentList.add(STANDARD_CATEGORY);
		methodContentList.add(CUSTOM_CATEGORY);
	}

	private static List guidanceList = new ArrayList();
	static {
		guidanceList.add(CHECKLIST);
		guidanceList.add(CONCEPT);
		guidanceList.add(ESTIMATION_CONSIDERATIONS);
		guidanceList.add(EXAMPLE);
		guidanceList.add(GUIDELINE);
		guidanceList.add(PRACTICE);
		guidanceList.add(REPORT);
		guidanceList.add(REUSABLE_ASSET);
		guidanceList.add(ROADMAP);
		guidanceList.add(SUPPORTING_MATERIAL);
		guidanceList.add(TEMPLATE);
		guidanceList.add(TERM_DEFINITION);
		guidanceList.add(TOOL_MENTOR);
		guidanceList.add(WHITEPAPER);
	}

	private static List processList = new ArrayList();
	static {
		processList.add(CAPABILITY_PATTERN);
		processList.add(DELIVERY_PROCESS);
	}

	private static List hasChildrenList = new ArrayList();
	static {
		hasChildrenList.add(ROOT);
		hasChildrenList.add(METHOD_CONTENT);
		hasChildrenList.add(GUIDANCE);
		hasChildrenList.add(PROCESS);
	}

	private CheckboxTreeViewer viewer;

	/**
	 * The content provider for the viewer.
	 */
	private static class ViewerContentProvider implements ITreeContentProvider {

		private final Object[] EMPTY_LIST = new Object[0];

		public Object[] getElements(Object parent) {
			if (parent == ROOT) {
				return getChildren(ROOT);
			}
			return getChildren(parent);
		}

		public Object[] getChildren(Object parent) {
			if (parent == ROOT) {
				return rootList.toArray();
			} else if (parent == METHOD_CONTENT) {
				return methodContentList.toArray();
			} else if (parent == GUIDANCE) {
				return guidanceList.toArray();
			} else if (parent == PROCESS) {
				return processList.toArray();
			}
			return EMPTY_LIST;
		}

		public Object getParent(Object child) {
			if (rootList.contains(child)) {
				return ROOT;
			}
			if (methodContentList.contains(child)) {
				return METHOD_CONTENT;
			} else if (guidanceList.contains(child)) {
				return GUIDANCE;
			} else if (processList.contains(child)) {
				return PROCESS;
			}
			return EMPTY_LIST;
		}

		public boolean hasChildren(Object parent) {
			return hasChildrenList.contains(parent);
		}

		public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
		}

		public void dispose() {
		}

	}

	/**
	 * The label provider for the viewer.
	 */
	private static class ViewerLabelProvider extends LabelProvider {

		public String getText(Object obj) {
			return obj.toString();
		}

		public Image getImage(Object obj) {
			return null;
		}
	}

	/**
	 * Creates a new instance.
	 */
	public MethodSearchScopeViewer(Composite parent, int style) {
		viewer = new CheckboxTreeViewer(parent, style);
		viewer.getTree().setLayout(new GridLayout(1, false));
		viewer.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
		viewer.setContentProvider(new ViewerContentProvider());
		viewer.setLabelProvider(new ViewerLabelProvider());
		viewer.setInput(ROOT);
		viewer.expandToLevel(2);
		viewer.setSubtreeChecked(METHOD_CONTENT, true);
		viewer.setSubtreeChecked(PROCESS, true);
		viewer.addCheckStateListener(new ICheckStateListener() {
			public void checkStateChanged(CheckStateChangedEvent event) {
				Object selectedElement = event.getElement();
				viewer.setSubtreeChecked(selectedElement, event.getChecked());
				if (!event.getChecked()) {
					viewer.setParentsGrayed(selectedElement, true);
					viewer.setGrayChecked(selectedElement, false);
				} else {
					viewer.setParentsGrayed(selectedElement, false);
				}
			}
		});
	}

	/**
	 * Returns the selected method element types.
	 * 
	 * @return an array of selected method element types
	 */
	public MethodSearchScope getSearchScope() {
		return new MethodSearchScope(viewer.getCheckedElements());
	}

}
