/*******************************************************************************
 * Copyright (c) 2000, 2008 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 API and implementation
 *******************************************************************************/

package org.eclipse.remote.internal.ui;

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

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.model.IWorkbenchAdapter;
import org.eclipse.ui.progress.UIJob;

public class RemoteTreeViewer extends TreeViewer {
	private ExpansionJob fExpansionJob = null;
	private SelectionJob fSelectionJob = null;

	private class ExpansionJob extends UIJob {

		private Object element;
		private final List<Object> parents = new ArrayList<Object>(); // top down

		/**
		 * Constructs a job to expand the given element.
		 * 
		 */
		public ExpansionJob() {
			super("Expansion"); //$NON-NLS-1$
			setPriority(Job.INTERACTIVE);
			setSystem(true);
		}

		@Override
		public IStatus runInUIThread(IProgressMonitor monitor) {
			if (getControl().isDisposed() || element == null) {
				return Status.OK_STATUS;
			}
			synchronized (RemoteTreeViewer.this) {
				boolean allParentsExpanded = true;
				Iterator<Object> iterator = parents.iterator();
				while (iterator.hasNext() && !monitor.isCanceled()) {
					Object parent = iterator.next();
					Widget item = findItem(parent);
					if (item != null) {
						expandToLevel(parent, 1);
					} else {
						allParentsExpanded = false;
						break;
					}
				}
				if (allParentsExpanded) {
					Widget item = findItem(element);
					if (item != null) {
						if (isExpandable(element)) {
							expandToLevel(element, 1);
						}
						element = null;
						parents.clear();
						return Status.OK_STATUS;
					}
				}
				return Status.OK_STATUS;
			}
		}

		public void validate(Object object) {
			if (element != null) {
				if (element.equals(object) || parents.contains(object)) {
					cancel();
					element = null;
				}
			}
		}

		public void setDeferredExpansion(Object toExpand) {
			element = toExpand;
			parents.clear();
			addAllParents(parents, element);
		}

	}

	private class SelectionJob extends UIJob {

		private IStructuredSelection selection;
		private Object first;
		private final List<Object> parents = new ArrayList<Object>(); // top down

		/**
		 * Constucts a job to select the given element.
		 */
		public SelectionJob() {
			super("Selection"); //$NON-NLS-1$
			setPriority(Job.INTERACTIVE);
			setSystem(true);
		}

		@Override
		public IStatus runInUIThread(IProgressMonitor monitor) {
			if (getControl().isDisposed() || selection == null) {
				return Status.OK_STATUS;
			}
			synchronized (RemoteTreeViewer.this) {
				boolean allParentsExpanded = true;
				Iterator<Object> iterator = parents.iterator();
				while (iterator.hasNext() && !monitor.isCanceled()) {
					Object parent = iterator.next();
					Widget item = findItem(parent);
					if (item != null) {
						expandToLevel(parent, 1);
					} else {
						allParentsExpanded = false;
						break;
					}
				}
				if (allParentsExpanded) {
					if (findItem(first) != null) {
						setSelection(selection, true);
						selection = null;
						first = null;
						parents.clear();
						return Status.OK_STATUS;
					}
				}

				return Status.OK_STATUS;
			}
		}

		public void setDeferredSelection(IStructuredSelection sel) {
			selection = sel;
			first = selection.getFirstElement();
			parents.clear();
			addAllParents(parents, first);
		}

		public void validate(Object object) {
			if (first != null) {
				if (first.equals(object) || parents.contains(object)) {
					cancel();
					selection = null;
				}
			}
		}
	}

	/**
	 * Constructs a remote tree viewer parented by the given composite.
	 * 
	 * @param parent
	 *            parent composite
	 */
	public RemoteTreeViewer(Composite parent) {
		super(parent);
		addDisposeListener();
		fExpansionJob = new ExpansionJob();
		fSelectionJob = new SelectionJob();
	}

	/**
	 * Constructs a remote tree viewer parented by the given composite
	 * with the given style.
	 * 
	 * @param parent
	 *            parent composite
	 * @param style
	 *            style bits
	 */
	public RemoteTreeViewer(Composite parent, int style) {
		super(parent, style);
		addDisposeListener();
		fExpansionJob = new ExpansionJob();
		fSelectionJob = new SelectionJob();
	}

	/**
	 * Constructs a remote tree viewer with the given tree.
	 * 
	 * @param tree
	 *            tree widget
	 */
	public RemoteTreeViewer(Tree tree) {
		super(tree);
		addDisposeListener();
		fExpansionJob = new ExpansionJob();
		fSelectionJob = new SelectionJob();
	}

	private void addDisposeListener() {
		getControl().addDisposeListener(new DisposeListener() {
			@Override
			public void widgetDisposed(DisposeEvent e) {
				cancelJobs();
			}
		});
	}

	protected void runDeferredUpdates() {
		if (fExpansionJob != null) {
			fExpansionJob.schedule();
		}
		if (fSelectionJob != null) {
			fSelectionJob.schedule();
		}
	}

	/**
	 * The given element is being removed from the tree. Cancel
	 * any deferred updates for the element.
	 * 
	 * @param element
	 */
	protected void validateDeferredUpdates(Object element) {
		if (element != null) {
			if (fExpansionJob != null) {
				fExpansionJob.validate(element);
			}
			if (fSelectionJob != null) {
				fSelectionJob.validate(element);
			}
		}
	}

	@Override
	public synchronized void add(Object parentElement, Object childElement) {
		super.add(parentElement, childElement);
		runDeferredUpdates();
	}

	@Override
	public synchronized void add(Object parentElement, Object... childElements) {
		super.add(parentElement, childElements);
		runDeferredUpdates();
	}

	@Override
	public synchronized void remove(Object element) {
		validateDeferredUpdates(element);
		super.remove(element);
	}

	@Override
	public synchronized void remove(Object... elements) {
		for (Object element : elements) {
			validateDeferredUpdates(element);
		}
		super.remove(elements);
	}

	/**
	 * Cancels any deferred updates currently scheduled/running.
	 */
	public void cancelJobs() {
		cancel(fSelectionJob);
		cancel(fExpansionJob);
	}

	public synchronized void deferExpansion(Object element) {
		TreeItem treeItem = (TreeItem) findItem(element);
		if (treeItem == null) {
			fExpansionJob.setDeferredExpansion(element);
			fExpansionJob.schedule();
		} else {
			if (!getExpanded(treeItem)) {
				fExpansionJob.setDeferredExpansion(element);
				fExpansionJob.schedule();
			}
		}
	}

	public synchronized void deferSelection(IStructuredSelection selection) {
		if (fSelectionJob == null) {
			fSelectionJob = new SelectionJob();
		}

		fSelectionJob.setDeferredSelection(selection);
		fSelectionJob.schedule();
	}

	public IStructuredSelection getDeferredSelection() {
		if (fSelectionJob != null) {
			return fSelectionJob.selection;
		}
		return null;
	}

	private void cancel(Job job) {
		if (job != null) {
			job.cancel();
		}
	}

	private void addAllParents(List<Object> list, Object element) {
		if (element instanceof IAdaptable) {
			IAdaptable adaptable = (IAdaptable) element;
			IWorkbenchAdapter adapter = (IWorkbenchAdapter) adaptable.getAdapter(IWorkbenchAdapter.class);
			if (adapter != null) {
				Object parent = adapter.getParent(element);
				if (parent != null) {
					list.add(0, parent);
					addAllParents(list, parent);
				}
			}
		}
	}

	@Override
	public Object[] filter(Object[] elements) {
		return super.filter(elements);
	}

	public Object[] getCurrentChildren(Object parent) {
		Widget widget = findItem(parent);
		if (widget != null) {
			Item[] items = getChildren(widget);
			Object[] children = new Object[items.length];
			for (int i = 0; i < children.length; i++) {
				Object data = items[i].getData();
				if (data == null) {
					return null;
				}
				children[i] = data;
			}
			return children;
		}
		return null;
	}

	public synchronized void prune(final Object parent, final int offset) {
		Widget widget = findItem(parent);
		if (widget != null) {
			final Item[] currentChildren = getChildren(widget);
			if (offset < currentChildren.length) {
				preservingSelection(new Runnable() {
					@Override
					public void run() {
						for (int i = offset; i < currentChildren.length; i++) {
							if (currentChildren[i].getData() != null) {
								disassociate(currentChildren[i]);
							}
							currentChildren[i].dispose();
						}
					}
				});
			}
		}
	}

	public synchronized void replace(final Object parent, final Object[] children, final int offset) {
		preservingSelection(new Runnable() {
			@Override
			public void run() {
				Widget widget = findItem(parent);
				if (widget == null) {
					add(parent, children);
				} else {
					Item[] currentChildren = getChildren(widget);
					int pos = offset;
					if (pos >= currentChildren.length) {
						// append
						add(parent, children);
					} else {
						// replace
						for (int i = 0; i < children.length; i++) {
							Object child = children[i];
							if (pos < currentChildren.length) {
								// replace
								Item item = currentChildren[pos];
								Object data = item.getData();
								if (!child.equals(data)) {
									// no need to cancel pending updates here, the child may have shifted up/down
									internalRefresh(item, child, true, true);
								} else {
									// If it's the same child, the label/content may still have changed
									doUpdateItem(item, child);
									updatePlus(item, child);
								}
							} else {
								// add
								int numLeft = children.length - i;
								if (numLeft > 1) {
									Object[] others = new Object[numLeft];
									System.arraycopy(children, i, others, 0, numLeft);
									add(parent, others);
								} else {
									add(parent, child);
								}
								break;
							}
							pos++;
						}
					}
				}
				runDeferredUpdates();
			}
		});
	}

}
