/*******************************************************************************
 * Copyright (c) 2000, 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 API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.browsing;

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

import org.eclipse.core.resources.IResource;

import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;

import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.IBasicPropertyConstants;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;

import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IImportContainer;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageDeclaration;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IParent;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.IWorkingCopy;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;

import org.eclipse.jdt.ui.StandardJavaElementContentProvider;

import org.eclipse.jdt.internal.ui.JavaPlugin;

class JavaBrowsingContentProvider extends StandardJavaElementContentProvider implements IElementChangedListener {

	private StructuredViewer fViewer;
	private Object fInput;
	private JavaBrowsingPart fBrowsingPart;
	private int fReadsInDisplayThread;


	public JavaBrowsingContentProvider(boolean provideMembers, JavaBrowsingPart browsingPart) {
		super(provideMembers);
		fBrowsingPart= browsingPart;
		fViewer= fBrowsingPart.getViewer();
		JavaCore.addElementChangedListener(this);
	}

	public boolean hasChildren(Object element) {
		startReadInDisplayThread();
		try{
			return super.hasChildren(element);
		} finally {
			finishedReadInDisplayThread();
		}
	}

	public Object[] getChildren(Object element) {
		if (!exists(element))
			return NO_CHILDREN;

		startReadInDisplayThread();
		try {
			if (element instanceof Collection) {
				Collection elements= (Collection)element;
				if (elements.isEmpty())
					return NO_CHILDREN;
				Object[] result= new Object[0];
				Iterator iter= ((Collection)element).iterator();
				while (iter.hasNext()) {
					Object[] children= getChildren(iter.next());
					if (children != NO_CHILDREN)
						result= concatenate(result, children);
				}
				return result;
			}
			if (element instanceof IPackageFragment)
				return getPackageContents((IPackageFragment)element);
			if (fProvideMembers && element instanceof IType)
				return getChildren((IType)element);
			if (fProvideMembers && element instanceof ISourceReference && element instanceof IParent)
				return removeImportAndPackageDeclarations(super.getChildren(element));
			if (element instanceof IJavaProject)
				return getPackageFragmentRoots((IJavaProject)element);
			return super.getChildren(element);
		} catch (JavaModelException e) {
			return NO_CHILDREN;
		} finally {
			finishedReadInDisplayThread();
		}
	}

	private Object[] getPackageContents(IPackageFragment fragment) throws JavaModelException {
		ISourceReference[] sourceRefs;
		if (fragment.getKind() == IPackageFragmentRoot.K_SOURCE) {
			sourceRefs= fragment.getCompilationUnits();
		}
		else {
			IClassFile[] classFiles= fragment.getClassFiles();
			List topLevelClassFile= new ArrayList();
			for (int i= 0; i < classFiles.length; i++) {
				IType type= classFiles[i].getType();
				if (type != null && type.getDeclaringType() == null && !type.isAnonymous() && !type.isLocal())
					topLevelClassFile.add(classFiles[i]);
			}
			sourceRefs= (ISourceReference[])topLevelClassFile.toArray(new ISourceReference[topLevelClassFile.size()]);
		}

		Object[] result= new Object[0];
		for (int i= 0; i < sourceRefs.length; i++)
			result= concatenate(result, removeImportAndPackageDeclarations(getChildren(sourceRefs[i])));
		return concatenate(result, fragment.getNonJavaResources());
	}

	private Object[] removeImportAndPackageDeclarations(Object[] members) {
		ArrayList tempResult= new ArrayList(members.length);
		for (int i= 0; i < members.length; i++)
			if (!(members[i] instanceof IImportContainer) && !(members[i] instanceof IPackageDeclaration))
				tempResult.add(members[i]);
		return tempResult.toArray();
	}

	private Object[] getChildren(IType type) throws JavaModelException{
		IParent parent;
		if (type.isBinary())
			parent= type.getClassFile();
		else {
			parent= type.getCompilationUnit();
		}
		if (type.getDeclaringType() != null)
			return type.getChildren();

		// Add import declarations
		IJavaElement[] members= parent.getChildren();
		ArrayList tempResult= new ArrayList(members.length);
		for (int i= 0; i < members.length; i++)
			if ((members[i] instanceof IImportContainer))
				tempResult.add(members[i]);
		tempResult.addAll(Arrays.asList(type.getChildren()));
		return tempResult.toArray();
	}

	protected Object[] getPackageFragmentRoots(IJavaProject project) throws JavaModelException {
		if (!project.getProject().isOpen())
			return NO_CHILDREN;

		IPackageFragmentRoot[] roots= project.getPackageFragmentRoots();
		List list= new ArrayList(roots.length);
		// filter out package fragments that correspond to projects and
		// replace them with the package fragments directly
		for (int i= 0; i < roots.length; i++) {
			IPackageFragmentRoot root= roots[i];
			if (!root.isExternal()) {
				Object[] children= root.getChildren();
				for (int k= 0; k < children.length; k++)
					list.add(children[k]);
			}
			else if (hasChildren(root)) {
				list.add(root);
			}
		}
		return concatenate(list.toArray(), project.getNonJavaResources());
	}

	// ---------------- Element change handling

	/* (non-Javadoc)
	 * Method declared on IContentProvider.
	 */
	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		super.inputChanged(viewer, oldInput, newInput);

		if (newInput instanceof Collection) {
			// Get a template object from the collection
			Collection col= (Collection)newInput;
			if (!col.isEmpty())
				newInput= col.iterator().next();
			else
				newInput= null;
		}
		fInput= newInput;
	}

	/* (non-Javadoc)
	 * Method declared on IContentProvider.
	 */
	public void dispose() {
		super.dispose();
		JavaCore.removeElementChangedListener(this);
	}

	/* (non-Javadoc)
	 * Method declared on IElementChangedListener.
	 */
	public void elementChanged(final ElementChangedEvent event) {
		try {
			processDelta(event.getDelta());
		} catch(JavaModelException e) {
			JavaPlugin.log(e.getStatus());
		}
	}


	/**
	 * Processes a delta recursively. When more than two children are affected the
	 * tree is fully refreshed starting at this node. The delta is processed in the
	 * current thread but the viewer updates are posted to the UI thread.
	 */
	protected void processDelta(IJavaElementDelta delta) throws JavaModelException {
		int kind= delta.getKind();
		int flags= delta.getFlags();
		final IJavaElement element= delta.getElement();
		final boolean isElementValidForView= fBrowsingPart.isValidElement(element);

		if (!getProvideWorkingCopy() && element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy())
			return;

		if (element != null && element.getElementType() == IJavaElement.COMPILATION_UNIT && !isOnClassPath((ICompilationUnit)element))
			return;

		// handle open and closing of a solution or project
		if (((flags & IJavaElementDelta.F_CLOSED) != 0) || ((flags & IJavaElementDelta.F_OPENED) != 0)) {
			postRefresh(null);
			return;
		}

		if (kind == IJavaElementDelta.REMOVED) {
			Object parent= internalGetParent(element);
			if (isElementValidForView) {
				if (element instanceof IClassFile) {
					postRemove(((IClassFile)element).getType());
				} else if (element instanceof ICompilationUnit && !((ICompilationUnit)element).isWorkingCopy()) {
						postRefresh(null);
				} else if (element instanceof ICompilationUnit && ((ICompilationUnit)element).isWorkingCopy()) {
					if (getProvideWorkingCopy())
						postRefresh(null);
				} else if (parent instanceof ICompilationUnit && getProvideWorkingCopy() && !((ICompilationUnit)parent).isWorkingCopy()) {
					if (element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy()) {
						// working copy removed from system - refresh
						postRefresh(null);
					}
				} else if (element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy() && parent != null && parent.equals(fInput))
					// closed editor - removing working copy
					postRefresh(null);
				else
					postRemove(element);
			}

			if (fBrowsingPart.isAncestorOf(element, fInput)) {
				if (element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy()) {
					postAdjustInputAndSetSelection(((IJavaElement) fInput).getPrimaryElement());
				} else
					postAdjustInputAndSetSelection(null);
			}

			if (fInput != null && fInput.equals(element))
				postRefresh(null);

			if (parent instanceof IPackageFragment && fBrowsingPart.isValidElement(parent))  {
				// refresh if package gets empty (might be filtered)
				if (isPackageFragmentEmpty((IPackageFragment)parent) && fViewer.testFindItem(parent) != null)
						postRefresh(null);
			}

			return;
		}
		if (kind == IJavaElementDelta.ADDED && delta.getMovedFromElement() != null && element instanceof ICompilationUnit)
			return;

		if (kind == IJavaElementDelta.ADDED) {
			if (isElementValidForView) {
				Object parent= internalGetParent(element);
				if (element instanceof IClassFile) {
					postAdd(parent, ((IClassFile)element).getType());
				} else if (element instanceof ICompilationUnit && !((ICompilationUnit)element).isWorkingCopy()) {
						postAdd(parent, ((ICompilationUnit)element).getTypes());
				} else if (parent instanceof ICompilationUnit && getProvideWorkingCopy() && !((ICompilationUnit)parent).isWorkingCopy()) {
					//	do nothing
				} else if (element instanceof IWorkingCopy && ((IWorkingCopy)element).isWorkingCopy()) {
					// new working copy comes to live
					postRefresh(null);
				} else
					postAdd(parent, element);
			} else	if (fInput == null) {
				IJavaElement newInput= fBrowsingPart.findInputForJavaElement(element);
				if (newInput != null)
					postAdjustInputAndSetSelection(element);
			} else if (element instanceof IType && fBrowsingPart.isValidInput(element)) {
				IJavaElement cu1= element.getAncestor(IJavaElement.COMPILATION_UNIT);
				IJavaElement cu2= ((IJavaElement)fInput).getAncestor(IJavaElement.COMPILATION_UNIT);
				if  (cu1 != null && cu2 != null && cu1.equals(cu2))
					postAdjustInputAndSetSelection(element);
			}
			return;
		}

		if (kind == IJavaElementDelta.CHANGED) {
			if (fInput != null && fInput.equals(element) && (flags & IJavaElementDelta.F_CHILDREN) != 0 && (flags & IJavaElementDelta.F_FINE_GRAINED) != 0) {
				postRefresh(null, true);
				return;
			}
			if (isElementValidForView && (flags & IJavaElementDelta.F_MODIFIERS) != 0) {
					postUpdateIcon(element);
			}
		}

		if (isClassPathChange(delta))
			 // throw the towel and do a full refresh
			postRefresh(null);

		if ((flags & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0 && fInput instanceof IJavaElement) {
			IPackageFragmentRoot pkgRoot= (IPackageFragmentRoot)element;
			IJavaElement inputsParent= ((IJavaElement)fInput).getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
			if (pkgRoot.equals(inputsParent))
				postRefresh(null);
		}

		// the source attachment of a JAR has changed
		if (element instanceof IPackageFragmentRoot && (((flags & IJavaElementDelta.F_SOURCEATTACHED) != 0 || ((flags & IJavaElementDelta.F_SOURCEDETACHED)) != 0)))
			postUpdateIcon(element);

		IJavaElementDelta[] affectedChildren= delta.getAffectedChildren();
		if (affectedChildren.length > 1) {
			// a package fragment might become non empty refresh from the parent
			if (element instanceof IPackageFragment) {
				IJavaElement parent= (IJavaElement)internalGetParent(element);
				// avoid posting a refresh to an invisible parent
				if (element.equals(fInput)) {
					postRefresh(element);
				} else {
					postRefresh(parent);
				}
			}
			// more than one child changed, refresh from here downwards
			if (element instanceof IPackageFragmentRoot && isElementValidForView) {
				postRefresh(skipProjectPackageFragmentRoot((IPackageFragmentRoot)element));
				return;
			}
		}
		for (int i= 0; i < affectedChildren.length; i++) {
			processDelta(affectedChildren[i]);
		}
	}

	private boolean isOnClassPath(ICompilationUnit element) throws JavaModelException {
		IJavaProject project= element.getJavaProject();
		if (project == null || !project.exists())
			return false;
		return project.isOnClasspath(element);
	}

	/**
	 * Updates the package icon
	 */
	 private void postUpdateIcon(final IJavaElement element) {
	 	postRunnable(new Runnable() {
			public void run() {
				Control ctrl= fViewer.getControl();
				if (ctrl != null && !ctrl.isDisposed())
					fViewer.update(element, new String[]{IBasicPropertyConstants.P_IMAGE});
			}
		});
	 }

	private void postRefresh(final Object root, final boolean updateLabels) {
		postRunnable(new Runnable() {
			public void run() {
				Control ctrl= fViewer.getControl();
				if (ctrl != null && !ctrl.isDisposed())
					fViewer.refresh(root, updateLabels);
			}
		});
	}

	private void postRefresh(final Object root) {
		postRefresh(root, false);
	}

	private void postAdd(final Object parent, final Object element) {
		postAdd(parent, new Object[] {element});
	}

	private void postAdd(final Object parent, final Object[] elements) {
		if (elements == null || elements.length <= 0)
			return;

		postRunnable(new Runnable() {
			public void run() {
				Control ctrl= fViewer.getControl();
				if (ctrl != null && !ctrl.isDisposed()) {
					Object[] newElements= getNewElements(elements);
					if (fViewer instanceof AbstractTreeViewer) {
						if (fViewer.testFindItem(parent) == null) {
							Object root= ((AbstractTreeViewer)fViewer).getInput();
							if (root != null)
								((AbstractTreeViewer)fViewer).add(root, newElements);
						}
						else
							((AbstractTreeViewer)fViewer).add(parent, newElements);
					}
					else if (fViewer instanceof ListViewer)
						((ListViewer)fViewer).add(newElements);
					else if (fViewer instanceof TableViewer)
						((TableViewer)fViewer).add(newElements);
					if (fViewer.testFindItem(elements[0]) != null)
						fBrowsingPart.adjustInputAndSetSelection(elements[0]);
				}
			}
		});
	}

	private Object[] getNewElements(Object[] elements) {
		int elementsLength= elements.length;
		ArrayList result= new ArrayList(elementsLength);
		for (int i= 0; i < elementsLength; i++) {
			Object element= elements[i];
			if (fViewer.testFindItem(element) == null)
				result.add(element);
		}
		return result.toArray();
	}

	private void postRemove(final Object element) {
		postRemove(new Object[] {element});
	}

	private void postRemove(final Object[] elements) {
		if (elements.length <= 0)
			return;

		postRunnable(new Runnable() {
			public void run() {
				Control ctrl= fViewer.getControl();
				if (ctrl != null && !ctrl.isDisposed()) {
					if (fViewer instanceof AbstractTreeViewer)
						((AbstractTreeViewer)fViewer).remove(elements);
					else if (fViewer instanceof ListViewer)
						((ListViewer)fViewer).remove(elements);
					else if (fViewer instanceof TableViewer)
						((TableViewer)fViewer).remove(elements);
				}
			}
		});
	}

	private void postAdjustInputAndSetSelection(final Object element) {
		postRunnable(new Runnable() {
			public void run() {
				Control ctrl= fViewer.getControl();
				if (ctrl != null && !ctrl.isDisposed()) {
					ctrl.setRedraw(false);
					fBrowsingPart.adjustInputAndSetSelection(element);
					ctrl.setRedraw(true);
				}
			}
		});
	}

	protected void startReadInDisplayThread() {
		if (isDisplayThread())
			fReadsInDisplayThread++;
	}

	protected void finishedReadInDisplayThread() {
		if (isDisplayThread())
			fReadsInDisplayThread--;
	}

	private boolean isDisplayThread() {
		Control ctrl= fViewer.getControl();
		if (ctrl == null)
			return false;

		Display currentDisplay= Display.getCurrent();
		return currentDisplay != null && currentDisplay.equals(ctrl.getDisplay());
	}

	private void postRunnable(final Runnable r) {
		Control ctrl= fViewer.getControl();
		if (ctrl != null && !ctrl.isDisposed()) {
			fBrowsingPart.setProcessSelectionEvents(false);
			try {
				if (isDisplayThread() && fReadsInDisplayThread == 0)
					ctrl.getDisplay().syncExec(r);
				else
					ctrl.getDisplay().asyncExec(r);
			} finally {
				fBrowsingPart.setProcessSelectionEvents(true);
			}
		}
	}

	/**
	 * Returns the parent for the element.
	 * <p>
	 * Note: This method will return a working copy if the
	 * parent is a working copy. The super class implementation
	 * returns the original element instead.
	 * </p>
	 */
	protected Object internalGetParent(Object element) {
		if (element instanceof IJavaProject) {
			return ((IJavaProject)element).getJavaModel();
		}
		// try to map resources to the containing package fragment
		if (element instanceof IResource) {
			IResource parent= ((IResource)element).getParent();
			Object jParent= JavaCore.create(parent);
			if (jParent != null)
				return jParent;
			return parent;
		}

		// for package fragments that are contained in a project package fragment
		// we have to skip the package fragment root as the parent.
		if (element instanceof IPackageFragment) {
			IPackageFragmentRoot parent= (IPackageFragmentRoot)((IPackageFragment)element).getParent();
			return skipProjectPackageFragmentRoot(parent);
		}
		if (element instanceof IJavaElement)
			return ((IJavaElement)element).getParent();

		return null;
	}
}
