//------------------------------------------------------------------------------
// 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.selectContentWizardPage_title);
		setDescription(PublishingUIResources.selectContentWizardPage_text);
		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));

		radio_entireConfig = createRadioButton(
				composite,
				PublishingUIResources.publishConfigRadioButton_text, 1, true);

		radio_processes = createRadioButton(
				composite,
				PublishingUIResources.publishProcessesRadioButton_text, 1, false);

		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.includeBaseProcessesCheckboxLabel_text); 
		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.capabilityPatterns_text;

		String NODE_DP = PublishingUIResources.deliveryProcesses_text;

		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$
			}
		}
	}

}
