//------------------------------------------------------------------------------
// 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.publishing.wizards;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.LibraryServiceUtil;
import org.eclipse.epf.library.configuration.ConfigurationHelper;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.publishing.services.PublishOptions;
import org.eclipse.epf.publishing.ui.PublishingUIResources;
import org.eclipse.epf.ui.wizards.BaseWizardPage;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodPlugin;
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.jface.wizard.IWizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;

/**
 * The Select publishing proceses wizard.
 * 
 * @author Jinhua Xi
 * @since 1.0
 */
public class PublishConfigSelectProcessPage extends BaseWizardPage implements
		Listener {

	private Button radio_entireConfig;

	private Button radio_processes;

	private Composite processContainer;

	private Button includeBaseProcesses;
	
	// private List check_processes = new ArrayList();

	Map checkBoxTpProcMap = new HashMap();

	CheckboxTreeViewer procViewer;

	private PublishOptions dataModel = null;

	/**
	 * Creates a new instance.
	 */
	public PublishConfigSelectProcessPage(String pageName,
			PublishOptions dataModel) {
		super(pageName);
		setTitle(PublishingUIResources.PublishConfigSelectProcessPage_title); //$NON-NLS-1$
		setDescription(PublishingUIResources.PublishConfigSelectProcessPage_text); //$NON-NLS-1$
		this.dataModel = dataModel;
	}

	/**
	 * @see org.eclipse.jface.dialogs.IDialogPage#createControl(Composite)
	 */
	public void createControl(Composite parent) {
		// Create the composite to hold the widgets.
		Composite composite = new Composite(parent, SWT.NULL);
		composite.setLayout(new GridLayout(1, false));

		createLabel(
				composite,
				PublishingUIResources.PublishConfigSelectProcessPage_label_selectType); //$NON-NLS-1$

		radio_entireConfig = createRadioButton(
				composite,
				PublishingUIResources.PublishConfigSelectProcessPage_label_type_config, 1, true); //$NON-NLS-1$

		radio_processes = createRadioButton(
				composite,
				PublishingUIResources.PublishConfigSelectProcessPage_label_type_processes, 1, false); //$NON-NLS-1$

		processContainer = new Composite(composite, SWT.NONE);
		processContainer.setLayoutData(new GridData(GridData.FILL_BOTH
				| GridData.GRAB_VERTICAL));
		GridLayout layout = new GridLayout();
		layout.marginLeft = 13;
		processContainer.setLayout(layout);

		createProcessContainer(processContainer);

		radio_entireConfig.addListener(SWT.Selection, this);
		radio_processes.addListener(SWT.Selection, this);

		processContainer.setVisible(radio_processes.getSelection());

		setControl(composite);
		setPageComplete(true);
	}

	private void createProcessContainer(Composite parent) {
		createTreeViewer(parent);
		includeBaseProcesses = createCheckbox(parent, 
				PublishingUIResources.PublishConfigSelectProcessPage_label_publish_base_processes); 
		includeBaseProcesses.addListener(SWT.Selection, this);
	}
	
	private void createTreeViewer(Composite parent) {
		procViewer = new CheckboxTreeViewer(parent);
		{
			GridData gridData = new GridData(GridData.FILL_BOTH
					| GridData.GRAB_HORIZONTAL);
			gridData.heightHint = 300;
			procViewer.getTree().setLayoutData(gridData);
		}
		procViewer.setContentProvider(new ProcessContentProvider());
		procViewer.setLabelProvider(new ProcessLabelProvider());

		procViewer.addCheckStateListener(new ICheckStateListener() {
			public void checkStateChanged(CheckStateChangedEvent event) {
				boolean checked = event.getChecked();
				updateCheckStates(event.getElement(), checked);
				selectbaseProcesses();
				
				setPageComplete(isPageComplete());
				getWizard().getContainer().updateButtons();

			}
		});

		String selecedConfigName = dataModel.getSelectedConfig();
		MethodConfiguration config = LibraryServiceUtil.getMethodConfiguration(
				LibraryService.getInstance().getCurrentMethodLibrary(),
				selecedConfigName);

		procViewer.setInput(config);

		procViewer.expandAll();
	}

	private void updateCheckStates(Object element, boolean checked) {

		// Object element = event.getElement();

		if (checked == true) {
			ITreeContentProvider cp = (ITreeContentProvider) procViewer
					.getContentProvider();
			checkParent(cp, element);
		} else
			procViewer.setChecked(element, false);

		selectionChildren(element, checked);

	}

	private void checkParent(ITreeContentProvider cp, Object element) {
		// if (element == null ) {
		// return;
		// }
		// Object parent = cp.getParent(element);
		// if (parent != null) {
		// procViewer.setChecked(parent, true);
		// checkParent(cp, parent);
		// }

	}

	private void selectionChildren(Object element, boolean checked) {
		ITreeContentProvider cp = (ITreeContentProvider) procViewer
				.getContentProvider();
		Object[] childs = cp.getChildren(element);
		for (int i = 0; i < childs.length; i++) {
			procViewer.setChecked(childs[i], checked);
			selectionChildren(childs[i], checked);
		}
	}

	/**
	 * handle the event
	 * @param event Event
	 */
	public void handleEvent(Event event) {

		if ( event.widget == includeBaseProcesses ) {
			// if selected, alto select all base processes
			selectbaseProcesses();
		}

		processContainer.setVisible(radio_processes.getSelection());

		setPageComplete(isPageComplete());
		getWizard().getContainer().updateButtons();
	}

	/**
	 * get the next Wizard page
	 * 
	 * @return IWizardPage
	 */
	public IWizardPage getNextPage() {

		return super.getNextPage();
	}

	/**
	 * check if the page is completed or not
	 * @return boolean
	 */
	public boolean isPageComplete() {
		if (getErrorMessage() != null)
			return false;

		dataModel.publishProcess = false;
		if (radio_entireConfig.getSelection()) {
			dataModel.publishConfiguration = true;
			return true;
		} else {
			List procs = getSelectedProcesses();

			// for (int i = 0; i < check_processes.size(); i++) {
			// Button b = (Button) check_processes.get(i);
			// if (b.getSelection()) {
			//
			// // set the selections
			// procs.add(checkBoxTpProcMap.get(b));
			// }
			// }

//			Object[] selected = procViewer.getCheckedElements();
//			if (selected != null && selected.length > 0) {
//				for (int i = 0; i < selected.length; i++) {
//					if (selected[i] instanceof org.eclipse.epf.uma.Process) {
//						procs.add(selected[i]);
//					}
//				}
//			}
			if (procs.size() > 0) {
				dataModel.publishProcess = true;
				dataModel.publishConfiguration = false;
				dataModel.setDeliverProcessList(procs);
				return true;
			}
		}

		return false;
	}

	private List getSelectedProcesses() {
		List procs = new ArrayList();

		Object[] selected = procViewer.getCheckedElements();
		if (selected != null && selected.length > 0) {
			for (int i = 0; i < selected.length; i++) {
				if (selected[i] instanceof org.eclipse.epf.uma.Process) {
					procs.add(selected[i]);
				}
			}
		}
		
		return procs;
	}
	
	private void selectbaseProcesses() {
		if ( !includeBaseProcesses.getSelection() ) {
			return;
		}
		
		String selecedConfigName = dataModel.getSelectedConfig();
		MethodConfiguration config = LibraryServiceUtil.getMethodConfiguration(
				LibraryService.getInstance().getCurrentMethodLibrary(),
				selecedConfigName);

		List procs = getSelectedProcesses();
		List bases = new ArrayList();
		for (Iterator it = procs.iterator(); it.hasNext(); ) {
			ConfigurationHelper.getBaseProcesses((Activity)it.next(), config, bases);
		}
		
		// update the selections
		for (Iterator it = bases.iterator(); it.hasNext(); ) {
			Object element = it.next();
			procViewer.setChecked(element, true);
			updateCheckStates(element, true);
		}		
	}
	
	private class ProcessContentProvider implements ITreeContentProvider {

		MethodConfiguration input = null;

		String NODE_CP = PublishingUIResources.PublishConfigSelectProcessPage_label_capability_pattern; //$NON-NLS-1$

		String NODE_DP = PublishingUIResources.PublishConfigSelectProcessPage_label_delivery_process; //$NON-NLS-1$

		String[] DPCP_NODES = new String[] { NODE_CP, NODE_DP };

		public Object[] getChildren(Object parentElement) {
			if (parentElement instanceof MethodConfiguration) {
				return DPCP_NODES;
			} else if (NODE_CP.equals(parentElement.toString())
					|| NODE_DP.equals(parentElement.toString())) {
				return getPlugins(parentElement).toArray();
			} else if (parentElement instanceof PluginNode) {
				Object parent = ((PluginNode) parentElement).parent;
				if (NODE_CP.equals(parent.toString())) {
					return ConfigurationHelper.getAllCapabilityPatterns(
							((PluginNode) parentElement).plugin, input)
							.toArray();
				} else if (NODE_DP.equals(parent.toString())) {
					return ConfigurationHelper.getAllDeliveryProcesses(
							((PluginNode) parentElement).plugin, input)
							.toArray();
				}
			}

			return new Object[] {};
		}

		public Object getParent(Object element) {
			if (element instanceof String) {
				return null;
			} else if (element instanceof PluginNode) {
				return ((PluginNode) element).parent;
			} else if (element instanceof org.eclipse.epf.uma.Process) {
				EObject o = (EObject) element;
				while ((o != null) && !(o instanceof MethodPlugin)) {
					o = o.eContainer();
				}

				return o;
			}

			return null;
		}

		public boolean hasChildren(Object element) {
			if (element instanceof PluginNode || element instanceof String) {
				return true;
			} else {
				return false;
			}
		}

		public Object[] getElements(Object inputElement) {
			return getChildren(inputElement);
		}

		public void dispose() {
			pluginNodeMap.clear();
			input = null;
		}

		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
			if (newInput instanceof MethodConfiguration) {
				input = (MethodConfiguration) newInput;
			} else {
				input = null;
			}

			pluginNodeMap.clear();
		}

		private List getPlugins(Object parent) {
			List validItems = new ArrayList();
			if (input != null) {
				List plugins = input.getMethodPluginSelection();
				for (Iterator it = plugins.iterator(); it.hasNext();) {
					MethodPlugin plugin = (MethodPlugin) it.next();
					List procs = null;
					if (NODE_CP.equals(parent.toString())) {
						procs = ConfigurationHelper.getAllCapabilityPatterns(
								plugin, input);
					} else if (NODE_DP.equals(parent.toString())) {
						procs = ConfigurationHelper.getAllDeliveryProcesses(
								plugin, input);
					}

					if (procs != null && procs.size() > 0) {
						validItems.add(getPluginNode(parent, plugin));
					}
				}
			}
			return validItems;
		}

		Map pluginNodeMap = new HashMap();

		private PluginNode getPluginNode(Object parent, MethodPlugin plugin) {
			String key = parent.toString() + ":" + plugin.getName(); //$NON-NLS-1$
			PluginNode node = (PluginNode) pluginNodeMap.get(key);
			if (node == null) {
				node = new PluginNode(parent, plugin);
				pluginNodeMap.put(key, node);
			}

			return node;
		}

		class PluginNode {
			Object parent;

			MethodPlugin plugin;

			public PluginNode(Object parent, MethodPlugin plugin) {
				this.parent = parent;
				this.plugin = plugin;
			}

			public String toString() {
				return plugin.getName();
			}
		}
	}

	private class ProcessLabelProvider extends LabelProvider {

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

		public String getText(Object element) {
			if (element instanceof org.eclipse.epf.uma.Process) {
				// ((org.eclipse.epf.uma.Process)element).getPresentationName()
				org.eclipse.epf.uma.Process proc = (org.eclipse.epf.uma.Process) element;
				return TngUtil.getPresentationName(proc);
			} else {
				return (element == null) ? "" : element.toString(); //$NON-NLS-1$
			}
		}
	}

}
