/*******************************************************************************
 * Copyright (c) 2005, 2017 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
 *
 *******************************************************************************/
package org.eclipse.dltk.internal.core;

import java.util.ArrayList;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IModelElementDelta;

public class ModelElementDelta extends SimpleDelta
		implements IModelElementDelta {

	/**
	 * Empty array of IModelElementDelta
	 */
	protected static final IModelElementDelta[] EMPTY_DELTA = new IModelElementDelta[] {};

	protected IModelElementDelta[] affectedChildren = EMPTY_DELTA;

	/*
	 * The element that this delta describes the change to.
	 */
	protected IModelElement changedElement;

	/**
	 * Collection of resource deltas that correspond to nonscriptresources
	 * deltas.
	 */
	protected IResourceDelta[] resourceDeltas = null;

	/**
	 * Counter of resource deltas
	 */
	protected int resourceDeltasCounter;
	/**
	 * @see #getMovedFromElement()
	 */
	protected IModelElement movedFromHandle = null;
	/**
	 * @see #getMovedToElement()
	 */
	protected IModelElement movedToHandle = null;

	/**
	 * Creates the root delta. To create the nested delta hierarchies use the
	 * following convenience methods. The root delta can be created at any level
	 * (for example: project, package root, package fragment...).
	 * <ul>
	 * <li><code>added(IModelElement)</code>
	 * <li><code>changed(IModelElement)</code>
	 * <li><code>moved(IModelElement, IModelElement)</code>
	 * <li><code>removed(IModelElement)</code>
	 * <li><code>renamed(IModelElement, IModelElement)</code>
	 * </ul>
	 */
	public ModelElementDelta(IModelElement element) {
		this.changedElement = element;
	}

	/**
	 * Creates the nested deltas resulting from an add operation. Convenience
	 * method for creating add deltas. The constructor should be used to create
	 * the root delta and then an add operation should call this method.
	 */
	public void added(IModelElement element) {
		added(element, 0);
	}

	public void added(IModelElement element, int flags) {
		ModelElementDelta addedDelta = new ModelElementDelta(element);
		addedDelta.added();
		addedDelta.changeFlags |= flags;
		insertDeltaTree(element, addedDelta);
	}

	/**
	 * Creates the nested deltas resulting from an delete operation. Convenience
	 * method for creating removed deltas. The constructor should be used to
	 * create the root delta and then the delete operation should call this
	 * method.
	 */
	public void removed(IModelElement element) {
		removed(element, 0);
	}

	public void removed(IModelElement element, int flags) {
		ModelElementDelta removedDelta = new ModelElementDelta(element);
		insertDeltaTree(element, removedDelta);
		ModelElementDelta actualDelta = getDeltaFor(element);
		if (actualDelta != null) {
			actualDelta.removed();
			actualDelta.changeFlags |= flags;
			actualDelta.affectedChildren = EMPTY_DELTA;
		}
	}

	/**
	 * Returns the delta for a given element. Only looks below this delta.
	 */
	protected ModelElementDelta getDeltaFor(IModelElement element) {
		if (this.equalsAndSameParent(getElement(), element)) // handle case of
																// two archives
																// that can be
																// equals but
																// not in the
																// same project
			return this;
		if (this.affectedChildren.length == 0)
			return null;
		int childrenCount = this.affectedChildren.length;
		for (int i = 0; i < childrenCount; i++) {
			ModelElementDelta delta = (ModelElementDelta) this.affectedChildren[i];
			if (this.equalsAndSameParent(delta.getElement(), element)) { // handle
																			// case
																			// of
																			// two
																			// archives
																			// that
																			// can
																			// be
																			// equals
																			// but
																			// not
																			// in
																			// the
																			// same
																			// project
				return delta;
			} else {
				delta = delta.getDeltaFor(element);
				if (delta != null)
					return delta;
			}
		}
		return null;
	}

	/**
	 * Adds the child delta to the collection of affected children. If the child
	 * is already in the collection, walk down the hierarchy.
	 */
	protected void addAffectedChild(ModelElementDelta child) {
		switch (this.kind) {
		case ADDED:
		case REMOVED:
			// no need to add a child if this parent is added or removed
			return;
		case CHANGED:
			this.changeFlags |= F_CHILDREN;
			break;
		default:
			this.kind = CHANGED;
			this.changeFlags |= F_CHILDREN;
		}

		// if a child delta is added to a compilation unit delta or below,
		// it's a fine grained delta
		if (this.changedElement
				.getElementType() >= IModelElement.SOURCE_MODULE) {
			this.fineGrained();
		}

		if (this.affectedChildren == null
				|| this.affectedChildren.length == 0) {
			this.affectedChildren = new IModelElementDelta[] { child };
			return;
		}
		ModelElementDelta existingChild = null;
		int existingChildIndex = -1;
		if (this.affectedChildren != null) {
			for (int i = 0; i < this.affectedChildren.length; i++) {
				if (this.equalsAndSameParent(
						this.affectedChildren[i].getElement(),
						child.getElement())) { // handle case of two archives
												// that can be equals but not in
												// the same project
					existingChild = (ModelElementDelta) this.affectedChildren[i];
					existingChildIndex = i;
					break;
				}
			}
		}
		if (existingChild == null) { // new affected child
			this.affectedChildren = growAndAddToArray(this.affectedChildren,
					child);
		} else {
			switch (existingChild.getKind()) {
			case ADDED:
				switch (child.getKind()) {
				case ADDED: // child was added then added -> it is added
				case CHANGED: // child was added then changed -> it is added
					return;
				case REMOVED: // child was added then removed -> noop
					this.affectedChildren = this.removeAndShrinkArray(
							this.affectedChildren, existingChildIndex);
					return;
				}
				break;
			case REMOVED:
				switch (child.getKind()) {
				case ADDED: // child was removed then added -> it is changed
					child.kind = CHANGED;
					this.affectedChildren[existingChildIndex] = child;
					return;
				case CHANGED: // child was removed then changed -> it is removed
				case REMOVED: // child was removed then removed -> it is removed
					return;
				}
				break;
			case CHANGED:
				switch (child.getKind()) {
				case ADDED: // child was changed then added -> it is added
				case REMOVED: // child was changed then removed -> it is removed
					this.affectedChildren[existingChildIndex] = child;
					return;
				case CHANGED: // child was changed then changed -> it is changed
					IModelElementDelta[] children = child.getAffectedChildren();
					for (int i = 0; i < children.length; i++) {
						ModelElementDelta childsChild = (ModelElementDelta) children[i];
						existingChild.addAffectedChild(childsChild);
					}

					// update flags
					boolean childHadContentFlag = (child.changeFlags
							& F_CONTENT) != 0;
					boolean existingChildHadChildrenFlag = (existingChild.changeFlags
							& F_CHILDREN) != 0;
					existingChild.changeFlags |= child.changeFlags;

					// remove F_CONTENT flag if existing child had F_CHILDREN
					// flag set
					// (case of fine grained delta (existing child) and delta
					// coming from
					// DeltaProcessor (child))
					if (childHadContentFlag && existingChildHadChildrenFlag) {
						existingChild.changeFlags &= ~F_CONTENT;
					}

					// add the non-java resource deltas if needed
					// note that the child delta always takes precedence over
					// this existing child delta
					// as non-java resource deltas are always created last (by
					// the DeltaProcessor)
					IResourceDelta[] resDeltas = child.getResourceDeltas();
					if (resDeltas != null) {
						existingChild.resourceDeltas = resDeltas;
						existingChild.resourceDeltasCounter = child.resourceDeltasCounter;
					}

					return;
				}
				break;
			default:
				// unknown -> existing child becomes the child with the existing
				// child's flags
				int flags = existingChild.getFlags();
				this.affectedChildren[existingChildIndex] = child;
				child.changeFlags |= flags;
			}
		}
	}

	@Override
	public IModelElement getElement() {
		return this.changedElement;
	}

	/**
	 * Creates the nested deltas resulting from a change operation. Convenience
	 * method for creating change deltas. The constructor should be used to
	 * create the root delta and then a change operation should call this
	 * method.
	 */
	public ModelElementDelta changed(IModelElement element, int changeFlag) {
		ModelElementDelta changedDelta = new ModelElementDelta(element);
		changedDelta.changed(changeFlag);
		insertDeltaTree(element, changedDelta);
		return changedDelta;
	}

	/**
	 * Creates the delta tree for the given element and delta, and then inserts
	 * the tree as an affected child of this node.
	 */
	protected void insertDeltaTree(IModelElement element,
			ModelElementDelta delta) {
		ModelElementDelta childDelta = createDeltaTree(element, delta);
		if (!this.equalsAndSameParent(element, getElement())) { // handle case
																// of two
																// archives that
																// can be equals
																// but not in
																// the same
																// project
			addAffectedChild(childDelta);
		}
	}

	/**
	 * Creates the nested delta deltas based on the affected element its delta,
	 * and the root of this delta tree. Returns the root of the created delta
	 * tree.
	 */
	protected ModelElementDelta createDeltaTree(IModelElement element,
			ModelElementDelta delta) {
		ModelElementDelta childDelta = delta;
		ArrayList<IModelElement> ancestors = getAncestors(element);
		if (ancestors == null) {
			if (this.equalsAndSameParent(delta.getElement(), getElement())) { // handle
																				// case
																				// of
																				// two
																				// archives
																				// that
																				// can
																				// be
																				// equals
																				// but
																				// not
																				// in
																				// the
																				// same
																				// project
				// the element being changed is the root element
				this.kind = delta.kind;
				this.changeFlags = delta.changeFlags;
				this.movedToHandle = delta.movedToHandle;
				this.movedFromHandle = delta.movedFromHandle;
			}
		} else {
			for (int i = 0, size = ancestors.size(); i < size; i++) {
				IModelElement ancestor = ancestors.get(i);
				ModelElementDelta ancestorDelta = new ModelElementDelta(
						ancestor);
				ancestorDelta.addAffectedChild(childDelta);
				childDelta = ancestorDelta;
			}
		}
		return childDelta;
	}

	/**
	 * Returns whether the two script elements are equals and have the same
	 * parent.
	 */
	protected boolean equalsAndSameParent(IModelElement e1, IModelElement e2) {
		IModelElement parent1;
		return e1.equals(e2) && ((parent1 = e1.getParent()) != null)
				&& parent1.equals(e2.getParent());
	}

	@Override
	public IModelElementDelta[] getAddedChildren() {
		return getChildrenOfType(ADDED);
	}

	@Override
	public IModelElementDelta[] getAffectedChildren() {
		return this.affectedChildren;
	}

	/**
	 * Returns a collection of all the parents of this element up to (but not
	 * including) the root of this tree in bottom-up order. If the given element
	 * is not a descendant of the root of this tree, <code>null</code> is
	 * returned.
	 */
	private ArrayList<IModelElement> getAncestors(IModelElement element) {
		IModelElement parent = element.getParent();
		if (parent == null) {
			return null;
		}
		ArrayList<IModelElement> parents = new ArrayList<>();
		while (!parent.equals(this.changedElement)) {
			parents.add(parent);
			parent = parent.getParent();
			if (parent == null) {
				return null;
			}
		}
		parents.trimToSize();
		return parents;
	}

	/**
	 * Adds the new element to a new array that contains all of the elements of
	 * the old array. Returns the new array.
	 */
	protected IModelElementDelta[] growAndAddToArray(IModelElementDelta[] array,
			IModelElementDelta addition) {
		IModelElementDelta[] old = array;
		array = new IModelElementDelta[old.length + 1];
		System.arraycopy(old, 0, array, 0, old.length);
		array[old.length] = addition;
		return array;
	}

	/**
	 * Removes the element from the array. Returns the a new array which has
	 * shrunk.
	 */
	protected IModelElementDelta[] removeAndShrinkArray(
			IModelElementDelta[] old, int index) {
		IModelElementDelta[] array = new IModelElementDelta[old.length - 1];
		if (index > 0)
			System.arraycopy(old, 0, array, 0, index);
		int rest = old.length - index - 1;
		if (rest > 0)
			System.arraycopy(old, index + 1, array, index, rest);
		return array;
	}

	/**
	 * Mark this delta as a fine-grained delta.
	 */
	public void fineGrained() {
		changed(F_FINE_GRAINED);
	}

	/**
	 * Return the collection of resource deltas. Return null if none.
	 */
	@Override
	public IResourceDelta[] getResourceDeltas() {
		if (resourceDeltas == null)
			return null;
		if (resourceDeltas.length != resourceDeltasCounter) {
			System.arraycopy(resourceDeltas, 0,
					resourceDeltas = new IResourceDelta[resourceDeltasCounter],
					0, resourceDeltasCounter);
		}
		return resourceDeltas;
	}

	/**
	 * Removes the child delta from the collection of affected children.
	 */
	protected void removeAffectedChild(ModelElementDelta child) {
		int index = -1;
		if (this.affectedChildren != null) {
			for (int i = 0; i < this.affectedChildren.length; i++) {
				if (this.equalsAndSameParent(
						this.affectedChildren[i].getElement(),
						child.getElement())) { // handle case of two archives
												// that can be equals but not in
												// the same project
					index = i;
					break;
				}
			}
		}
		if (index >= 0) {
			this.affectedChildren = removeAndShrinkArray(this.affectedChildren,
					index);
		}
	}

	/**
	 * Mark this delta as a content changed delta.
	 */
	public void contentChanged() {
		this.changeFlags |= F_CONTENT;
	}

	/**
	 * Creates the nested deltas resulting from an move operation. Convenience
	 * method for creating the "move from" delta. The constructor should be used
	 * to create the root delta and then the move operation should call this
	 * method.
	 */
	public void movedFrom(IModelElement movedFromElement,
			IModelElement movedToElement) {
		ModelElementDelta removedDelta = new ModelElementDelta(
				movedFromElement);
		removedDelta.kind = REMOVED;
		removedDelta.changeFlags |= F_MOVED_TO;
		removedDelta.movedToHandle = movedToElement;
		insertDeltaTree(movedFromElement, removedDelta);
	}

	/**
	 * Creates the nested deltas resulting from an move operation. Convenience
	 * method for creating the "move to" delta. The constructor should be used
	 * to create the root delta and then the move operation should call this
	 * method.
	 */
	public void movedTo(IModelElement movedToElement,
			IModelElement movedFromElement) {
		ModelElementDelta addedDelta = new ModelElementDelta(movedToElement);
		addedDelta.kind = ADDED;
		addedDelta.changeFlags |= F_MOVED_FROM;
		addedDelta.movedFromHandle = movedFromElement;
		insertDeltaTree(movedToElement, addedDelta);
	}

	protected void addResourceDelta(IResource resource) {
		addResourceDelta(new ResourceChangeToNonScriptDelta(resource));
	}

	/**
	 * Adds the child delta to the collection of affected children. If the child
	 * is already in the collection, walk down the hierarchy.
	 */
	protected void addResourceDelta(IResourceDelta child) {
		switch (this.kind) {
		case ADDED:
		case REMOVED:
			// no need to add a child if this parent is added or removed
			return;
		case CHANGED:
			this.changeFlags |= F_CONTENT;
			break;
		default:
			this.kind = CHANGED;
			this.changeFlags |= F_CONTENT;
		}
		if (resourceDeltas == null) {
			resourceDeltas = new IResourceDelta[5];
			resourceDeltas[resourceDeltasCounter++] = child;
			return;
		}
		if (resourceDeltas.length == resourceDeltasCounter) {
			// need a resize
			System.arraycopy(resourceDeltas, 0,
					(resourceDeltas = new IResourceDelta[resourceDeltasCounter
							* 2]),
					0, resourceDeltasCounter);
		}
		resourceDeltas[resourceDeltasCounter++] = child;
	}

	/**
	 * Returns the <code>ModelElementDelta</code> for the given element in the
	 * delta tree, or null, if no delta for the given element is found.
	 */
	protected ModelElementDelta find(IModelElement e) {
		if (this.equalsAndSameParent(this.changedElement, e)) { // handle case
																// of two
																// archives that
																// can be equals
																// but not in
																// the same
																// project
			return this;
		} else {
			for (int i = 0; i < this.affectedChildren.length; i++) {
				ModelElementDelta delta = ((ModelElementDelta) this.affectedChildren[i])
						.find(e);
				if (delta != null) {
					return delta;
				}
			}
		}
		return null;
	}

	/**
	 * Creates the nested deltas for a closed element.
	 */
	public void closed(IModelElement element) {
		ModelElementDelta delta = new ModelElementDelta(element);
		delta.changed(F_CLOSED);
		insertDeltaTree(element, delta);
	}

	/**
	 * Creates the nested deltas for an opened element.
	 */
	public void opened(IModelElement element) {
		ModelElementDelta delta = new ModelElementDelta(element);
		delta.changed(F_OPENED);
		insertDeltaTree(element, delta);
	}

	/**
	 * @see IModelElementDelta
	 */
	protected IModelElementDelta[] getChildrenOfType(int type) {
		int length = affectedChildren.length;
		if (length == 0) {
			return new IModelElementDelta[] {};
		}
		ArrayList<IModelElementDelta> children = new ArrayList<>(
				length);
		for (int i = 0; i < length; i++) {
			if (affectedChildren[i].getKind() == type) {
				children.add(affectedChildren[i]);
			}
		}

		IModelElementDelta[] childrenOfType = new IModelElementDelta[children
				.size()];
		children.toArray(childrenOfType);

		return childrenOfType;
	}

	@Override
	public IModelElement getMovedFromElement() {
		return this.movedFromHandle;
	}

	@Override
	public IModelElement getMovedToElement() {
		return movedToHandle;
	}

	/**
	 * Returns a string representation of this delta's structure suitable for
	 * debug purposes.
	 *
	 * @see #toString()
	 */
	public String toDebugString(int depth) {
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < depth; i++) {
			buffer.append('\t');
		}
		buffer.append(((ModelElement) getElement()).toDebugString());
		toDebugString(buffer);
		IModelElementDelta[] children = getAffectedChildren();
		if (children != null) {
			for (int i = 0; i < children.length; ++i) {
				buffer.append("\n"); //$NON-NLS-1$
				buffer.append(((ModelElementDelta) children[i])
						.toDebugString(depth + 1));
			}
		}
		for (int i = 0; i < resourceDeltasCounter; i++) {
			buffer.append("\n");//$NON-NLS-1$
			for (int j = 0; j < depth + 1; j++) {
				buffer.append('\t');
			}
			IResourceDelta resourceDelta = resourceDeltas[i];
			buffer.append(resourceDelta.toString());
			buffer.append("["); //$NON-NLS-1$
			switch (resourceDelta.getKind()) {
			case IResourceDelta.ADDED:
				buffer.append('+');
				break;
			case IResourceDelta.REMOVED:
				buffer.append('-');
				break;
			case IResourceDelta.CHANGED:
				buffer.append('*');
				break;
			default:
				buffer.append('?');
				break;
			}
			buffer.append("]"); //$NON-NLS-1$
		}
		return buffer.toString();
	}

	@Override
	protected boolean toDebugString(StringBuffer buffer, int flags) {
		boolean prev = super.toDebugString(buffer, flags);

		if ((flags & IModelElementDelta.F_CHILDREN) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("CHILDREN"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_CONTENT) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("CONTENT"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_MOVED_FROM) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("MOVED_FROM(" + ((ModelElement) getMovedFromElement()) //$NON-NLS-1$
					.toStringWithAncestors() + ")"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_MOVED_TO) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("MOVED_TO(" + ((ModelElement) getMovedToElement()) //$NON-NLS-1$
					.toStringWithAncestors() + ")"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_ADDED_TO_BUILDPATH) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("ADDED TO BUILDPATH"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_REMOVED_FROM_BUILDPATH) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("REMOVED FROM BUILDPATH"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_REORDER) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("REORDERED"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("ARCHIVE CONTENT CHANGED"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_FINE_GRAINED) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("FINE GRAINED"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_PRIMARY_WORKING_COPY) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("PRIMARY WORKING COPY"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_BUILDPATH_CHANGED) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("BUILDPATH CHANGED"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_RESOLVED_BUILDPATH_CHANGED) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("RESOLVED BUILDPATH CHANGED"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_PRIMARY_RESOURCE) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("PRIMARY RESOURCE"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_OPENED) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("OPENED"); //$NON-NLS-1$
			prev = true;
		}
		if ((flags & IModelElementDelta.F_CLOSED) != 0) {
			if (prev)
				buffer.append(" | "); //$NON-NLS-1$
			buffer.append("CLOSED"); //$NON-NLS-1$
			prev = true;
		}
		return prev;
	}

	/**
	 * Returns a string representation of this delta's structure suitable for
	 * debug purposes.
	 */
	@Override
	public String toString() {
		return toDebugString(0);
	}
}
