/*******************************************************************************
 * Copyright (c) 2000, 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
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Vladimir Piskarev (1C) - adaptation (adapted from
 *         org.eclipse.jdt.internal.core.JavaElementDelta)
 *******************************************************************************/
package org.eclipse.handly.model.impl;

import static org.eclipse.handly.context.Contexts.EMPTY_CONTEXT;
import static org.eclipse.handly.context.Contexts.of;
import static org.eclipse.handly.context.Contexts.with;
import static org.eclipse.handly.model.IElementDeltaConstants.ADDED;
import static org.eclipse.handly.model.IElementDeltaConstants.CHANGED;
import static org.eclipse.handly.model.IElementDeltaConstants.F_CHILDREN;
import static org.eclipse.handly.model.IElementDeltaConstants.F_CONTENT;
import static org.eclipse.handly.model.IElementDeltaConstants.F_DESCRIPTION;
import static org.eclipse.handly.model.IElementDeltaConstants.F_FINE_GRAINED;
import static org.eclipse.handly.model.IElementDeltaConstants.F_MARKERS;
import static org.eclipse.handly.model.IElementDeltaConstants.F_MOVED_FROM;
import static org.eclipse.handly.model.IElementDeltaConstants.F_MOVED_TO;
import static org.eclipse.handly.model.IElementDeltaConstants.F_OPEN;
import static org.eclipse.handly.model.IElementDeltaConstants.F_REORDER;
import static org.eclipse.handly.model.IElementDeltaConstants.F_SYNC;
import static org.eclipse.handly.model.IElementDeltaConstants.F_UNDERLYING_RESOURCE;
import static org.eclipse.handly.model.IElementDeltaConstants.F_WORKING_COPY;
import static org.eclipse.handly.model.IElementDeltaConstants.REMOVED;
import static org.eclipse.handly.util.ToStringOptions.FORMAT_STYLE;
import static org.eclipse.handly.util.ToStringOptions.INDENT_LEVEL;
import static org.eclipse.handly.util.ToStringOptions.INDENT_POLICY;
import static org.eclipse.handly.util.ToStringOptions.FormatStyle.FULL;
import static org.eclipse.handly.util.ToStringOptions.FormatStyle.LONG;
import static org.eclipse.handly.util.ToStringOptions.FormatStyle.MEDIUM;
import static org.eclipse.handly.util.ToStringOptions.FormatStyle.SHORT;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.handly.context.IContext;
import org.eclipse.handly.model.Elements;
import org.eclipse.handly.model.IElement;
import org.eclipse.handly.model.ISourceElement;
import org.eclipse.handly.util.IndentPolicy;
import org.eclipse.handly.util.ToStringOptions.FormatStyle;

/**
 * Implementation of element delta. To create a delta tree, use the
 * {@link ElementDelta.Builder}.
 * <p>
 * Note that despite having a dependency on {@link IResourceDelta}
 * and {@link IMarkerDelta} this class can be used even when
 * <code>org.eclipse.core.resources</code> bundle is not available.
 * This is based on the "outward impression" of late resolution of
 * symbolic references a JVM must provide according to the JVMS.
 * </p>
 * <p>
 * Clients can use this class as it stands or subclass it as circumstances
 * warrant. Clients that subclass this class should consider registering
 * an appropriate {@link ElementDelta.Factory} in the model context.
 * </p>
 */
public class ElementDelta
    implements IElementDeltaImpl
{
    private static final ElementDelta[] NO_CHILDREN = new ElementDelta[0];

    private final IElement element;
    private int kind;
    private long flags;
    private IElement movedFromElement;
    private IElement movedToElement;
    private ElementDelta[] affectedChildren = NO_CHILDREN;

    /**
     * On-demand index into <code>affectedChildren</code>.
     * @see #indexOfChild(Key)
     * @see #hNeedsChildIndex()
     */
    private Map<Key, Integer> childIndex;

    private IMarkerDelta[] markerDeltas;
    private IResourceDelta[] resourceDeltas;
    private int resourceDeltasCounter;

    /**
     * Constructs an initially empty delta for the given element.
     *
     * @param element the element that this delta describes a change to
     *  (not <code>null</code>)
     * @see ElementDelta.Builder
     */
    public ElementDelta(IElement element)
    {
        if (element == null)
            throw new IllegalArgumentException();
        this.element = element;
    }

    @Override
    public final IElement hElement()
    {
        return element;
    }

    @Override
    public final int hKind()
    {
        return kind;
    }

    @Override
    public final long hFlags()
    {
        return flags;
    }

    @Override
    public final ElementDelta[] hAffectedChildren()
    {
        return affectedChildren;
    }

    @Override
    public final ElementDelta[] hAddedChildren()
    {
        return getChildrenOfKind(ADDED);
    }

    @Override
    public final ElementDelta[] hRemovedChildren()
    {
        return getChildrenOfKind(REMOVED);
    }

    @Override
    public final ElementDelta[] hChangedChildren()
    {
        return getChildrenOfKind(CHANGED);
    }

    @Override
    public final IElement hMovedFromElement()
    {
        return movedFromElement;
    }

    @Override
    public final IElement hMovedToElement()
    {
        return movedToElement;
    }

    @Override
    public final IMarkerDelta[] hMarkerDeltas()
    {
        return markerDeltas;
    }

    @Override
    public final IResourceDelta[] hResourceDeltas()
    {
        if (resourceDeltas != null
            && resourceDeltas.length != resourceDeltasCounter)
        {
            System.arraycopy(resourceDeltas, 0, resourceDeltas =
                new IResourceDelta[resourceDeltasCounter], 0,
                resourceDeltasCounter);
        }
        return resourceDeltas;
    }

    /**
     * Returns whether this delta is empty,
     * i.e. represents an unchanged element.
     *
     * @return <code>true</code> if this delta is empty,
     *  and <code>false</code> otherwise
     */
    public boolean hIsEmpty()
    {
        return hKind() == 0;
    }

    /**
     * Returns the delta for the given element in this delta subtree,
     * or <code>null</code> if no delta is found for the given element.
     *
     * @param element the element to search delta for or <code>null</code>
     * @return the delta for the given element, or <code>null</code> if none
     */
    public ElementDelta hDeltaFor(IElement element)
    {
        if (element == null)
            return null;
        if (Elements.equalsAndSameParent(this.element, element))
            return this;
        return findDescendant(new Key(element));
    }

    @Override
    public String toString()
    {
        return hToString(EMPTY_CONTEXT);
    }

    @Override
    public String hToString(IContext context)
    {
        StringBuilder builder = new StringBuilder();
        IndentPolicy indentPolicy = context.getOrDefault(INDENT_POLICY);
        int indentLevel = context.getOrDefault(INDENT_LEVEL);
        indentPolicy.appendIndent(builder, indentLevel);
        builder.append(Elements.toString(element, with(of(FORMAT_STYLE, SHORT),
            of(INDENT_LEVEL, 0), context)));
        builder.append('[');
        hToStringKind(builder, context);
        builder.append("]: {"); //$NON-NLS-1$
        hToStringFlags(builder, context);
        builder.append('}');
        FormatStyle style = context.getOrDefault(FORMAT_STYLE);
        if (style == FULL || style == LONG)
        {
            if (affectedChildren.length > 0)
            {
                indentPolicy.appendLine(builder);
                hToStringChildren(builder, with(of(INDENT_LEVEL, //
                    indentLevel + 1), context));
            }
            if (resourceDeltasCounter > 0)
            {
                indentPolicy.appendLine(builder);
                hToStringResourceDeltas(builder, with(of(INDENT_LEVEL,
                    indentLevel + 1), context));
            }
        }
        return builder.toString();
    }

    /**
     * Debugging purposes.
     */
    protected void hToStringChildren(StringBuilder builder, IContext context)
    {
        IndentPolicy indentPolicy = context.getOrDefault(INDENT_POLICY);
        for (int i = 0; i < affectedChildren.length; i++)
        {
            if (i > 0)
                indentPolicy.appendLine(builder);
            builder.append(affectedChildren[i].hToString(context));
        }
    }

    /**
     * Debugging purposes.
     */
    protected void hToStringResourceDeltas(StringBuilder builder,
        IContext context)
    {
        IndentPolicy indentPolicy = context.getOrDefault(INDENT_POLICY);
        int indentLevel = context.getOrDefault(INDENT_LEVEL);
        for (int i = 0; i < resourceDeltasCounter; i++)
        {
            if (i > 0)
                indentPolicy.appendLine(builder);
            indentPolicy.appendIndent(builder, indentLevel);
            IResourceDelta resourceDelta = resourceDeltas[i];
            builder.append("ResourceDelta(" + resourceDelta.getFullPath() //$NON-NLS-1$
                + ')');
            builder.append('[');
            switch (resourceDelta.getKind())
            {
            case IResourceDelta.ADDED:
                builder.append('+');
                break;
            case IResourceDelta.REMOVED:
                builder.append('-');
                break;
            case IResourceDelta.CHANGED:
                builder.append('*');
                break;
            default:
                builder.append('?');
                break;
            }
            builder.append(']');
        }
    }

    /**
     * Debugging purposes.
     */
    protected void hToStringKind(StringBuilder builder, IContext context)
    {
        switch (hKind())
        {
        case ADDED:
            builder.append('+');
            break;
        case REMOVED:
            builder.append('-');
            break;
        case CHANGED:
            builder.append('*');
            break;
        default:
            builder.append('?');
            break;
        }
    }

    /**
     * Debugging purposes.
     *
     * @param builder a string builder to append the delta flags to
     * @param context not <code>null</code>
     * @return <code>true</code> if a flag was appended to the builder,
     *  <code>false</code> if the builder was not modified by this method
     */
    protected boolean hToStringFlags(StringBuilder builder, IContext context)
    {
        boolean prev = false;
        long flags = hFlags();
        if ((flags & F_CHILDREN) != 0)
        {
            if (prev)
                builder.append(" | "); //$NON-NLS-1$
            builder.append("CHILDREN"); //$NON-NLS-1$
            prev = true;
        }
        if ((flags & F_CONTENT) != 0)
        {
            if (prev)
                builder.append(" | "); //$NON-NLS-1$
            builder.append("CONTENT"); //$NON-NLS-1$
            prev = true;
        }
        if ((flags & F_MOVED_FROM) != 0)
        {
            if (prev)
                builder.append(" | "); //$NON-NLS-1$
            builder.append("MOVED_FROM("); //$NON-NLS-1$
            builder.append(Elements.toString(hMovedFromElement(), with(of(
                FORMAT_STYLE, MEDIUM), of(INDENT_LEVEL, 0), context)));
            builder.append(')');
            prev = true;
        }
        if ((flags & F_MOVED_TO) != 0)
        {
            if (prev)
                builder.append(" | "); //$NON-NLS-1$
            builder.append("MOVED_TO("); //$NON-NLS-1$
            builder.append(Elements.toString(hMovedToElement(), with(of(
                FORMAT_STYLE, MEDIUM), of(INDENT_LEVEL, 0), context)));
            builder.append(')');
            prev = true;
        }
        if ((flags & F_REORDER) != 0)
        {
            if (prev)
                builder.append(" | "); //$NON-NLS-1$
            builder.append("REORDERED"); //$NON-NLS-1$
            prev = true;
        }
        if ((flags & F_FINE_GRAINED) != 0)
        {
            if (prev)
                builder.append(" | "); //$NON-NLS-1$
            builder.append("FINE GRAINED"); //$NON-NLS-1$
            prev = true;
        }
        if ((flags & F_OPEN) != 0)
        {
            if (prev)
                builder.append(" | "); //$NON-NLS-1$
            builder.append("OPEN"); //$NON-NLS-1$
            prev = true;
        }
        if ((flags & F_DESCRIPTION) != 0)
        {
            if (prev)
                builder.append(" | "); //$NON-NLS-1$
            builder.append("DESCRIPTION"); //$NON-NLS-1$
            prev = true;
        }
        if ((flags & F_WORKING_COPY) != 0)
        {
            if (prev)
                builder.append(" | "); //$NON-NLS-1$
            builder.append("WORKING COPY"); //$NON-NLS-1$
            prev = true;
        }
        if ((flags & F_UNDERLYING_RESOURCE) != 0)
        {
            if (prev)
                builder.append(" | "); //$NON-NLS-1$
            builder.append("UNDERLYING_RESOURCE"); //$NON-NLS-1$
            prev = true;
        }
        if ((flags & F_MARKERS) != 0)
        {
            if (prev)
                builder.append(" | "); //$NON-NLS-1$
            builder.append("MARKERS"); //$NON-NLS-1$
            prev = true;
        }
        if ((flags & F_SYNC) != 0)
        {
            if (prev)
                builder.append(" | "); //$NON-NLS-1$
            builder.append("SYNC"); //$NON-NLS-1$
            prev = true;
        }
        return prev;
    }

    /**
     * Returns a new, initially empty delta for the given element.
     * <p>
     * This implementation uses {@link ElementDelta.Factory} registered in the
     * element's model context. If no delta factory is registered in the model
     * context, a new instance of this class (i.e. <code>ElementDelta</code>)
     * is returned.
     * </p>
     *
     * @param element the element that this delta describes a change to
     *  (not <code>null</code>)
     * @return a new, initially empty delta for the given element
     *  (never <code>null</code>)
     */
    protected ElementDelta hNewDelta(IElement element)
    {
        Factory factory = Elements.getModel(element).getModelContext().get(
            Factory.class);
        if (factory != null)
            return factory.newDelta(element);
        return new ElementDelta(element);
    }

    /**
     * Returns whether the child index needs to be used for child lookup.
     *
     * @return <code>true</code> if the child index needs to be used,
     *  <code>false</code> otherwise
     */
    protected boolean hNeedsChildIndex()
    {
        return affectedChildren.length >= 3;
    }

    /**
     * Sets the kind of this delta.
     *
     * @param kind
     */
    protected void hSetKind(int kind)
    {
        this.kind = kind;
    }

    /**
     * Sets the flags for this delta.
     *
     * @param flags
     */
    protected void hSetFlags(long flags)
    {
        this.flags = flags;
    }

    /**
     * Sets an element describing this delta's element before it was moved
     * to its current location.
     * <p>
     * This is a low-level mutator method. In particular, it is the caller's
     * responsibility to set appropriate flags.
     * </p>
     *
     * @param movedFromElement
     */
    protected void hSetMovedFromElement(IElement movedFromElement)
    {
        this.movedFromElement = movedFromElement;
    }

    /**
     * Sets an element describing this delta's element in its new location.
     * <p>
     * This is a low-level mutator method. In particular, it is the caller's
     * responsibility to set appropriate flags.
     * </p>
     *
     * @param movedToElement
     */
    protected void hSetMovedToElement(IElement movedToElement)
    {
        this.movedToElement = movedToElement;
    }

    /**
     * Sets the marker deltas.
     * <p>
     * This is a low-level mutator method. In particular, it is the caller's
     * responsibility to set appropriate flags.
     * </p>
     *
     * @param markerDeltas
     */
    protected void hSetMarkerDeltas(IMarkerDelta[] markerDeltas)
    {
        this.markerDeltas = markerDeltas;
    }

    /**
     * Sets the resource deltas.
     * <p>
     * This is a low-level mutator method. In particular, it is the caller's
     * responsibility to set appropriate flags.
     * </p>
     *
     * @param resourceDeltas
     */
    protected void hSetResourceDeltas(IResourceDelta[] resourceDeltas)
    {
        this.resourceDeltas = resourceDeltas;
        this.resourceDeltasCounter = (resourceDeltas != null)
            ? resourceDeltas.length : 0;
    }

    /**
     * Adds the child resource delta to the collection of resource deltas.
     * <p>
     * This is a low-level mutator method. In particular, it is the caller's
     * responsibility to set appropriate flags.
     * </p>
     *
     * @param child the resource delta to add (not <code>null</code>)
     */
    protected void hAddResourceDelta(IResourceDelta child)
    {
        if (child == null)
            throw new IllegalArgumentException();

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

    /**
     * Creates a delta tree for the given delta, and then adds the tree
     * as an affected child of this delta.
     *
     * @param delta the delta to insert (not <code>null</code>)
     */
    protected void hInsert(ElementDelta delta)
    {
        if (delta == null)
            throw new IllegalArgumentException();
        if (!Elements.equalsAndSameParent(delta.element, element))
        {
            addAffectedChild(createDeltaTree(delta));
        }
        else
        {
            // the element being changed is the root delta's element
            hSetKind(delta.hKind());
            hSetFlags(delta.hFlags());
            hSetMovedToElement(delta.hMovedToElement());
            hSetMovedFromElement(delta.hMovedFromElement());
        }
    }

    /**
     * Clears the collection of affected children.
     */
    protected void hClearAffectedChildren()
    {
        affectedChildren = NO_CHILDREN;
        childIndex = null;
    }

    /**
     * Based on the given delta, creates a delta tree to add as an affected
     * child of this delta. Returns the root of the created delta tree.
     *
     * @param delta the delta to create a delta tree for (not <code>null</code>)
     * @return the root of the created delta tree (never <code>null</code>)
     */
    private ElementDelta createDeltaTree(ElementDelta delta)
    {
        ElementDelta childDelta = delta;
        List<IElement> ancestors = getAncestors(delta.element);
        if (ancestors == null)
        {
            IContext context = of(FORMAT_STYLE, SHORT);
            throw new IllegalArgumentException(MessageFormat.format(
                "Delta {0} cannot be rooted under {1}", delta.hToString( //$NON-NLS-1$
                    context), hToString(context)));
        }
        for (IElement ancestor : ancestors)
        {
            ElementDelta ancestorDelta = hNewDelta(ancestor);
            ancestorDelta.addAffectedChild(childDelta);
            childDelta = ancestorDelta;
        }
        return childDelta;
    }

    /**
     * Returns a collection of the parents of the given element up to (but
     * not including) the element of this delta in bottom-up order.
     * If the given element is not a descendant of this delta's element,
     * <code>null</code> is returned.
     *
     * @param child the given element (not <code>null</code>)
     * @return the collection of the parents of the given element up to
     *  (but not including) the element of this delta in bottom-up order,
     *  or <code>null</code> if the given element is not a descendant of
     *  this delta's element
     */
    private List<IElement> getAncestors(IElement child)
    {
        IElement parent = Elements.getParent(child);
        if (parent == null)
            return null;

        ArrayList<IElement> parents = new ArrayList<>();
        while (!parent.equals(element))
        {
            parents.add(parent);
            parent = Elements.getParent(parent);
            if (parent == null)
                return null;
        }
        parents.trimToSize();
        return parents;
    }

    /**
     * Returns the deltas for the affected children of the given kind.
     *
     * @param kind one of <code>ADDED</code>, <code>REMOVED</code>, or
     *  <code>CHANGED</code>
     * @return the deltas for the affected children of the given kind
     *  (never <code>null</code>)
     */
    private ElementDelta[] getChildrenOfKind(int kind)
    {
        int length = affectedChildren.length;
        if (length == 0)
            return NO_CHILDREN;

        ArrayList<ElementDelta> children = new ArrayList<>(length);
        for (ElementDelta child : affectedChildren)
        {
            if (child.hKind() == kind)
                children.add(child);
        }

        return children.toArray(NO_CHILDREN);
    }

    /**
     * Returns the delta for the given key in this delta subtree,
     * or <code>null</code> if no delta is found for the given key.
     *
     * @param key the key to search delta for (not <code>null</code>)
     * @return the delta for the given key, or <code>null</code> if none
     */
    private ElementDelta findDescendant(Key key)
    {
        if (affectedChildren.length == 0)
            return null;
        Integer index = indexOfChild(key);
        if (index != null)
            return affectedChildren[index];
        for (ElementDelta child : affectedChildren)
        {
            ElementDelta delta = child.findDescendant(key);
            if (delta != null)
                return delta;
        }
        return null;
    }

    /**
     * Given a delta key, returns the index of the delta in the collection
     * of affected children, or <code>null</code> if no child delta is found
     * for the given key.
     *
     * @param key the key to search child delta for (not <code>null</code>)
     * @return the index of the child delta for the given key,
     *  or <code>null</code> if not found
     */
    private Integer indexOfChild(Key key)
    {
        int length = affectedChildren.length;
        if (!hNeedsChildIndex())
        {
            for (int i = 0; i < length; i++)
            {
                if (Elements.equalsAndSameParent(key.element,
                    affectedChildren[i].element))
                {
                    return i;
                }
            }
            return null;
        }
        if (childIndex == null)
        {
            childIndex = new HashMap<Key, Integer>();
            for (int i = 0; i < length; i++)
            {
                childIndex.put(new Key(affectedChildren[i].element), i);
            }
        }
        return childIndex.get(key);
    }

    /**
     * Adds the given delta to the collection of affected children.
     * If the given delta is already in the collection, walks down
     * this delta tree.
     *
     * @param child the child delta to add (not <code>null</code>)
     */
    private void addAffectedChild(ElementDelta child)
    {
        if (child == null)
            throw new IllegalArgumentException();

        switch (hKind())
        {
        case ADDED:
        case REMOVED:
            // no need to add a child if this parent is added or removed
            return;
        case CHANGED:
            hSetFlags(hFlags() | F_CHILDREN);
            break;
        default:
            hSetKind(CHANGED);
            hSetFlags(hFlags() | F_CHILDREN);
        }

        // if a child delta is added to a source file delta or below,
        // it's a fine grained delta
        if (element instanceof ISourceElement)
        {
            hSetFlags(hFlags() | F_FINE_GRAINED);
        }

        Key key = new Key(child.element);
        Integer index = indexOfChild(key);
        if (index == null) // new affected child
        {
            addNewChild(child);
        }
        else
        {
            ElementDelta existingChild = affectedChildren[index];
            switch (existingChild.hKind())
            {
            case ADDED:
                switch (child.hKind())
                {
                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
                    removeExistingChild(key, index);
                    return;
                }
                break;
            case REMOVED:
                switch (child.hKind())
                {
                case ADDED: // child was removed then added -> it is changed
                    child.hSetKind(CHANGED);
                    affectedChildren[index] = 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.hKind())
                {
                case ADDED: // child was changed then added -> it is added
                case REMOVED: // child was changed then removed -> it is removed
                    affectedChildren[index] = child;
                    return;
                case CHANGED: // child was changed then changed -> it is changed
                    for (ElementDelta childsChild : child.affectedChildren)
                    {
                        existingChild.addAffectedChild(childsChild);
                    }

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

                    // remove F_CONTENT 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.hSetFlags(existingChild.hFlags()
                            & ~F_CONTENT);
                    }

                    // add marker deltas if needed
                    if (child.markerDeltas != null)
                    {
                        if (existingChild.markerDeltas != null)
                            throw new AssertionError(
                                "Merge of marker deltas is not supported"); //$NON-NLS-1$

                        existingChild.hSetMarkerDeltas(child.hMarkerDeltas());
                    }

                    // add resource deltas if needed
                    if (child.resourceDeltas != null)
                    {
                        if (existingChild.resourceDeltas != null)
                            throw new AssertionError(
                                "Merge of resource deltas is not supported"); //$NON-NLS-1$

                        existingChild.hSetResourceDeltas(
                            child.hResourceDeltas());
                    }

                    return;
                }
                break;
            default:
                // unknown -> existing child becomes the child with the existing child's flags
                affectedChildren[index] = child;
                child.hSetFlags(child.hFlags() | existingChild.hFlags());
            }
        }
    }

    /**
     * Adds a new child delta to the collection of affected children.
     *
     * @param child the child delta to add (not <code>null</code>)
     */
    private void addNewChild(ElementDelta child)
    {
        affectedChildren = growAndAddToArray(affectedChildren, child);
        if (childIndex != null)
        {
            childIndex.put(new Key(child.element), affectedChildren.length - 1);
        }
    }

    /**
     * Removes the specified child delta from the collection of affected children.
     *
     * @param key
     *  the key of the child delta (not <code>null</code>)
     * @param index
     *  the index of the child delta in the collection of affected children
     */
    private void removeExistingChild(Key key, int index)
    {
        affectedChildren = removeAndShrinkArray(affectedChildren, index);
        if (childIndex != null)
        {
            if (!hNeedsChildIndex())
                childIndex = null;
            else
            {
                childIndex.remove(key);
                for (int i = index; i < affectedChildren.length; i++)
                {
                    childIndex.put(new Key(affectedChildren[i].element), i);
                }
            }
        }
    }

    /**
     * Adds the given element to a new array that contains all
     * of the elements of the given array. Returns the new array.
     *
     * @param array the specified array (not <code>null</code>)
     * @param addition the element to add
     * @return the resulting array (never <code>null</code>)
     */
    private static ElementDelta[] growAndAddToArray(ElementDelta[] array,
        ElementDelta addition)
    {
        ElementDelta[] result = new ElementDelta[array.length + 1];
        System.arraycopy(array, 0, result, 0, array.length);
        result[array.length] = addition;
        return result;
    }

    /**
     * Copies the given array into a new array excluding
     * an element at the given index. Returns the new array.
     *
     * @param array the specified array (not <code>null</code>)
     * @param index a valid index which indicates the element to exclude
     * @return the resulting array (never <code>null</code>)
     */
    private static ElementDelta[] removeAndShrinkArray(ElementDelta[] array,
        int index)
    {
        ElementDelta[] result = new ElementDelta[array.length - 1];
        if (index > 0)
            System.arraycopy(array, 0, result, 0, index);
        int rest = array.length - index - 1;
        if (rest > 0)
            System.arraycopy(array, index + 1, result, index, rest);
        return result;
    }

    /**
     * Element delta factory.
     */
    public interface Factory
    {
        /**
         * Returns a new, initially empty delta for the given element.
         *
         * @param element the element that this delta describes a change to
         *  (not <code>null</code>)
         * @return a new, initially empty delta for the given element
         *  (never <code>null</code>)
         */
        ElementDelta newDelta(IElement element);
    }

    /**
     * Facility for building a delta tree.
     */
    public static class Builder
    {
        private final ElementDelta rootDelta;

        /**
         * Constructs a delta tree builder on the given root delta.
         *
         * @param rootDelta not <code>null</code>
         */
        public Builder(ElementDelta rootDelta)
        {
            if (rootDelta == null)
                throw new IllegalArgumentException();
            this.rootDelta = rootDelta;
        }

        /**
         * Returns the root of the delta tree.
         * Always returns the same instance for this builder.
         *
         * @return the root of delta tree (never <code>null</code>)
         */
        public ElementDelta getDelta()
        {
            return rootDelta;
        }

        /**
         * Returns whether the delta tree is empty,
         * i.e. represents an unchanged element.
         *
         * @return <code>true</code> if the delta is empty,
         *  and <code>false</code> otherwise
         */
        public boolean isEmptyDelta()
        {
            return rootDelta.hIsEmpty();
        }

        /**
         * Returns the delta for the given element in the delta tree,
         * or <code>null</code> if no delta is found for the element.
         *
         * @param element the element to search delta for or <code>null</code>
         * @return the delta for the given element, or <code>null</code> if none
         */
        public ElementDelta findDelta(IElement element)
        {
            return rootDelta.hDeltaFor(element);
        }

        /**
         * Has the same effect as <code>added(element, 0)</code>.
         *
         * @param element the added element (not <code>null</code>)
         * @return the receiver (i.e. a reference to this object)
         * @see #added(IElement, long)
         */
        public Builder added(IElement element)
        {
            return added(element, 0);
        }

        /**
         * Inserts an <code>ADDED</code> delta for the given element into
         * the delta tree being built.
         *
         * @param element the added element (not <code>null</code>)
         * @param flags delta flags (see {@link ElementDelta#hFlags})
         * @return the receiver (i.e. a reference to this object)
         */
        public Builder added(IElement element, long flags)
        {
            insert(newAdded(element, flags));
            return this;
        }

        /**
         * Has the same effect as <code>removed(element, 0)</code>.
         *
         * @param element the removed element (not <code>null</code>)
         * @return the receiver (i.e. a reference to this object)
         * @see #removed(IElement, long)
         */
        public Builder removed(IElement element)
        {
            return removed(element, 0);
        }

        /**
         * Inserts a <code>REMOVED</code> delta for the given element into
         * the delta tree being built.
         *
         * @param element the removed element (not <code>null</code>)
         * @param flags delta flags (see {@link ElementDelta#hFlags})
         * @return the receiver (i.e. a reference to this object)
         */
        public Builder removed(IElement element, long flags)
        {
            ElementDelta delta = rootDelta.hNewDelta(element);
            insert(delta);
            ElementDelta actualDelta = findDelta(element);
            if (actualDelta != null)
            {
                actualDelta.hSetKind(REMOVED);
                actualDelta.hSetFlags(flags);
                actualDelta.hClearAffectedChildren();
                actualDelta.hSetResourceDeltas(null);
                actualDelta.hSetMarkerDeltas(null);
            }
            return this;
        }

        /**
         * Inserts a <code>CHANGED</code> delta for the given element into
         * the delta tree being built.
         *
         * @param element the changed element (not <code>null</code>)
         * @param flags delta flags (see {@link ElementDelta#hFlags})
         * @return the receiver (i.e. a reference to this object)
         */
        public Builder changed(IElement element, long flags)
        {
            insert(newChanged(element, flags));
            return this;
        }

        /**
         * Inserts a new "moved from" (<code>REMOVED</code>) delta for the
         * given element into the delta tree being built.
         *
         * @param movedFromElement the element before it was moved to its
         *  current location (not <code>null</code>)
         * @param movedToElement the element in its new location
         *  (not <code>null</code>)
         * @return the receiver (i.e. a reference to this object)
         */
        public Builder movedFrom(IElement movedFromElement,
            IElement movedToElement)
        {
            insert(newMovedFrom(movedFromElement, movedToElement));
            return this;
        }

        /**
         * Inserts a new "moved to" (<code>ADDED</code>) delta for the
         * given element into the delta tree being built.
         *
         * @param movedToElement the element in its new location
         *  (not <code>null</code>)
         * @param movedFromElement the element before it was moved to its
         *  current location (not <code>null</code>)
         * @return the receiver (i.e. a reference to this object)
         */
        public Builder movedTo(IElement movedToElement,
            IElement movedFromElement)
        {
            insert(newMovedTo(movedToElement, movedFromElement));
            return this;
        }

        /**
         * Inserts a <code>CHANGED</code> delta with the specified marker
         * deltas for the given element into the delta tree being built.
         * Does nothing if the delta tree already contains an <code>ADDED</code>
         * or <code>REMOVED</code> delta for the given element.
         *
         * @param element the element with changed markers
         *  (not <code>null</code>)
         * @param markerDeltas the marker deltas for the element
         *  (not <code>null</code>, not empty)
         * @return the receiver (i.e. a reference to this object)
         */
        public Builder markersChanged(IElement element,
            IMarkerDelta[] markerDeltas)
        {
            if (markerDeltas == null || markerDeltas.length == 0)
                throw new IllegalArgumentException();

            ElementDelta delta = findDelta(element);
            if (delta == null)
            {
                changed(element, 0);
                delta = findDelta(element);
            }

            if (delta != null)
            {
                switch (delta.hKind())
                {
                case ADDED:
                case REMOVED:
                    break; // do nothing
                case CHANGED:
                    delta.hSetFlags(delta.hFlags() | F_MARKERS);
                    delta.hSetMarkerDeltas(markerDeltas);
                    break;
                default: // empty delta
                    delta.hSetKind(CHANGED);
                    delta.hSetFlags(delta.hFlags() | F_MARKERS);
                    delta.hSetMarkerDeltas(markerDeltas);
                }
            }
            return this;
        }

        /**
         * Inserts a <code>CHANGED</code> delta with the specified resource
         * delta for the given element into the delta tree being built.
         * Does nothing if the delta tree already contains an <code>ADDED</code>
         * or <code>REMOVED</code> delta for the given element.
         *
         * @param element the element with resource change
         *  (not <code>null</code>)
         * @param resourceDelta the resource delta for the element
         *  (not <code>null</code>)
         * @return the receiver (i.e. a reference to this object)
         */
        public Builder addResourceDelta(IElement element,
            IResourceDelta resourceDelta)
        {
            if (resourceDelta == null)
                throw new IllegalArgumentException();

            ElementDelta delta = findDelta(element);
            if (delta == null)
            {
                changed(element, 0);
                delta = findDelta(element);
            }

            if (delta != null)
            {
                switch (delta.hKind())
                {
                case ADDED:
                case REMOVED:
                    break; // do nothing
                case CHANGED:
                    delta.hSetFlags(delta.hFlags() | F_CONTENT);
                    delta.hAddResourceDelta(resourceDelta);
                    break;
                default: // empty delta
                    delta.hSetKind(CHANGED);
                    delta.hSetFlags(delta.hFlags() | F_CONTENT);
                    delta.hAddResourceDelta(resourceDelta);
                }
            }
            return this;
        }

        private void insert(ElementDelta delta)
        {
            rootDelta.hInsert(delta);
        }

        /**
         * Returns a new <code>ADDED</code> delta for the given element.
         *
         * @param element the element that this delta describes a change to
         *  (not <code>null</code>)
         * @param flags delta flags
         * @return a new <code>ADDED</code> delta for the given element
         *  (never <code>null</code>)
         */
        private ElementDelta newAdded(IElement element, long flags)
        {
            ElementDelta delta = rootDelta.hNewDelta(element);
            delta.hSetKind(ADDED);
            delta.hSetFlags(flags);
            return delta;
        }

        /**
         * Returns a new <code>REMOVED</code> delta for the given element.
         *
         * @param element the element that this delta describes a change to
         *  (not <code>null</code>)
         * @param flags delta flags
         * @return a new <code>REMOVED</code> delta for the given element
         *  (never <code>null</code>)
         */
        private ElementDelta newRemoved(IElement element, long flags)
        {
            ElementDelta delta = rootDelta.hNewDelta(element);
            delta.hSetKind(REMOVED);
            delta.hSetFlags(flags);
            return delta;
        }

        /**
         * Returns a new <code>CHANGED</code> delta for the given element.
         *
         * @param element the element that this delta describes a change to
         *  (not <code>null</code>)
         * @param flags delta flags
         * @return a new <code>CHANGED</code> delta for the given element
         *  (never <code>null</code>)
         */
        private ElementDelta newChanged(IElement element, long flags)
        {
            ElementDelta delta = rootDelta.hNewDelta(element);
            delta.hSetKind(CHANGED);
            delta.hSetFlags(flags);
            return delta;
        }

        /**
         * Returns a new "moved from" (<code>REMOVED</code>) delta for the
         * given element.
         *
         * @param movedFromElement the element before it was moved to its
         *  current location (not <code>null</code>)
         * @param movedToElement the element in its new location
         *  (not <code>null</code>)
         * @return a new "moved from" (<code>REMOVED</code>) delta
         *  (never <code>null</code>)
         */
        private ElementDelta newMovedFrom(IElement movedFromElement,
            IElement movedToElement)
        {
            ElementDelta delta = newRemoved(movedFromElement, F_MOVED_TO);
            if (movedToElement == null)
                throw new IllegalArgumentException();
            delta.hSetMovedToElement(movedToElement);
            return delta;
        }

        /**
         * Returns a new "moved to" (<code>ADDED</code>) delta for the given
         * element.
         *
         * @param movedToElement the element in its new location
         *  (not <code>null</code>)
         * @param movedFromElement the element before it was moved to its
         *  current location (not <code>null</code>)
         * @return a new "moved to" (<code>ADDED</code>) delta
         *  (never <code>null</code>)
         */
        private ElementDelta newMovedTo(IElement movedToElement,
            IElement movedFromElement)
        {
            ElementDelta delta = newAdded(movedToElement, F_MOVED_FROM);
            if (movedFromElement == null)
                throw new IllegalArgumentException();
            delta.hSetMovedFromElement(movedFromElement);
            return delta;
        }
    }

    /**
     * Represents a delta key.
     * @see ElementDelta#childIndex
     */
    private static class Key
    {
        public final IElement element;

        /**
         * Constructs a new delta key for the given element.
         *
         * @param element not <code>null</code>
         */
        public Key(IElement element)
        {
            if (element == null)
                throw new IllegalArgumentException();
            this.element = element;
        }

        @Override
        public int hashCode()
        {
            return element.hashCode();
        }

        @Override
        public boolean equals(Object obj)
        {
            if (!(obj instanceof Key))
                return false;
            return Elements.equalsAndSameParent(element, ((Key)obj).element);
        }
    }
}
