/*******************************************************************************
 * Copyright (c) 2000, 2005 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.jface.action;

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

import org.eclipse.jface.util.Policy;

/**
 * Abstract base class for all contribution managers, and standard implementation 
 * of <code>IContributionManager</code>. This class provides functionality 
 * common across the specific managers defined by this framework.
 * <p>
 * This class maintains a list of contribution items and a dirty flag, both as 
 * internal state. In addition to providing implementations of most 
 * <code>IContributionManager</code> methods, this class automatically
 * coalesces adjacent separators, hides beginning and ending separators,
 * and deals with dynamically changing sets of contributions. When the set
 * of contributions does change dynamically, the changes are propagated
 * to the control via the <code>update</code> method, which subclasses
 * must implement.
 * </p>
 * <p>
 * Note: A <code>ContributionItem</code> cannot be shared between different
 * <code>ContributionManager</code>s.
 * </p>
 */
public abstract class ContributionManager implements IContributionManager {

    //	Internal debug flag.
    //	protected static final boolean DEBUG = false;

    /**
     * The list of contribution items.
     */
    private List contributions = new ArrayList();

    /** 
     * Indicates whether the widgets are in sync with the contributions.
     */
    private boolean isDirty = true;

    /** 
     * Number of dynamic contribution items.
     */
    private int dynamicItems = 0;

    /**
     * The overrides for items of this manager
     */
    private IContributionManagerOverrides overrides;

    /**
     * Creates a new contribution manager.
     */
    protected ContributionManager() {
        // Do nothing.
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public void add(IAction action) {
        add(new ActionContributionItem(action));
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public void add(IContributionItem item) {
        if (allowItem(item)) {
            contributions.add(item);
            itemAdded(item);
        }
    }

    /**
     * Adds a contribution item to the start or end of the group 
     * with the given name.
     *
     * @param groupName the name of the group
     * @param item the contribution item
     * @param append <code>true</code> to add to the end of the group, 
     *   and <code>false</code> to add the beginning of the group
     * @exception IllegalArgumentException if there is no group with
     *   the given name
     */
    private void addToGroup(String groupName, IContributionItem item,
            boolean append) {
        int i;
        Iterator items = contributions.iterator();
        for (i = 0; items.hasNext(); i++) {
            IContributionItem o = (IContributionItem) items.next();
            if (o.isGroupMarker()) {
                String id = o.getId();
                if (id != null && id.equalsIgnoreCase(groupName)) {
                    i++;
                    if (append) {
                        for (; items.hasNext(); i++) {
                            IContributionItem ci = (IContributionItem) items
                                    .next();
                            if (ci.isGroupMarker())
                                break;
                        }
                    }
                    if (allowItem(item)) {
                        contributions.add(i, item);
                        itemAdded(item);
                    }
                    return;
                }
            }
        }
        throw new IllegalArgumentException("Group not found: " + groupName);//$NON-NLS-1$
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public void appendToGroup(String groupName, IAction action) {
        addToGroup(groupName, new ActionContributionItem(action), true);
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public void appendToGroup(String groupName, IContributionItem item) {
        addToGroup(groupName, item, true);
    }

    /**
     * This method allows subclasses of <code>ContributionManager</code> to prevent
     * certain items in the contributions list.  <code>ContributionManager</code>
     * will either block or allow an addition based on the result of this method
     * call.  This can be used to prevent duplication, for example.
     * @param itemToAdd The contribution item to be added; may be <code>null</code>.
     * @return <code>true</code> if the addition should be allowed; 
     * <code>false</code> otherwise.  The default implementation allows all items.
     * @since 3.0
     */
    protected boolean allowItem(IContributionItem itemToAdd) {
        return true;
    }

    /**
     * Internal debug method for printing statistics about this manager
     * to <code>System.out</code>.
     */
    protected void dumpStatistics() {
        int size = 0;
        if (contributions != null)
            size = contributions.size();

        System.out.println(this.toString());
        System.out.println("   Number of elements: " + size);//$NON-NLS-1$
        int sum = 0;
        for (int i = 0; i < size; i++)
            if (((IContributionItem) contributions.get(i)).isVisible())
                sum++;
        System.out.println("   Number of visible elements: " + sum);//$NON-NLS-1$
        System.out.println("   Is dirty: " + isDirty()); //$NON-NLS-1$
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public IContributionItem find(String id) {
        Iterator e = contributions.iterator();
        while (e.hasNext()) {
            IContributionItem item = (IContributionItem) e.next();
            String itemId = item.getId();
            if (itemId != null && itemId.equalsIgnoreCase(id))
                return item;
        }
        return null;
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public IContributionItem[] getItems() {
        IContributionItem[] items = new IContributionItem[contributions.size()];
        contributions.toArray(items);
        return items;
    }

    /**
     * The <code>ContributionManager</code> implementation of this
     * method declared on <code>IContributionManager</code> returns
     * the current overrides. If there is no overrides it lazily creates
     * one which overrides no item state.
     * 
     * @since 2.0
     */
    public IContributionManagerOverrides getOverrides() {
        if (overrides == null) {
            overrides = new IContributionManagerOverrides() {
                public Boolean getEnabled(IContributionItem item) {
                    return null;
                }

                public Integer getAccelerator(IContributionItem item) {
                    return null;
                }

                public String getAcceleratorText(IContributionItem item) {
                    return null;
                }

                public String getText(IContributionItem item) {
                    return null;
                }
            };
        }
        return overrides;
    }

    /**
     * Returns whether this contribution manager contains dynamic items. 
     * A dynamic contribution item contributes items conditionally, 
     * dependent on some internal state.
     *
     * @return <code>true</code> if this manager contains dynamic items, and
     *  <code>false</code> otherwise
     */
    protected boolean hasDynamicItems() {
        return (dynamicItems > 0);
    }

    /**
     * Returns the index of the item with the given id.
     * @param id The id of the item whose index is requested.
     *
     * @return <code>int</code> the index or -1 if the item is not found
     */
    public int indexOf(String id) {
        for (int i = 0; i < contributions.size(); i++) {
            IContributionItem item = (IContributionItem) contributions.get(i);
            String itemId = item.getId();
            if (itemId != null && itemId.equalsIgnoreCase(id))
                return i;
        }
        return -1;
    }

    /**
     * Returns the index of the object in the internal structure. This is different from 
     * <code>indexOf(String id)</code> since some contribution items may not have an id.
     *  
     * @param item The contribution item 
     * @return the index, or -1 if the item is not found
     * @since 3.0
     */
    protected int indexOf(IContributionItem item) {
        return contributions.indexOf(item);
    }

    /**
     * Insert the item at the given index.
     * 
     * @param index The index to be used for insertion
     * @param item The item to be inserted
     */
    public void insert(int index, IContributionItem item) {
        if (index > contributions.size())
            throw new IndexOutOfBoundsException(
                    "inserting " + item.getId() + " at " + index); //$NON-NLS-1$ //$NON-NLS-2$
        if (allowItem(item)) {
            contributions.add(index, item);
            itemAdded(item);
        }
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public void insertAfter(String ID, IAction action) {
        insertAfter(ID, new ActionContributionItem(action));
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public void insertAfter(String ID, IContributionItem item) {
        IContributionItem ci = find(ID);
        if (ci == null)
            throw new IllegalArgumentException("can't find ID");//$NON-NLS-1$
        int ix = contributions.indexOf(ci);
        if (ix >= 0) {
            // System.out.println("insert after: " + ix);
            if (allowItem(item)) {
                contributions.add(ix + 1, item);
                itemAdded(item);
            }
        }
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public void insertBefore(String ID, IAction action) {
        insertBefore(ID, new ActionContributionItem(action));
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public void insertBefore(String ID, IContributionItem item) {
        IContributionItem ci = find(ID);
        if (ci == null)
            throw new IllegalArgumentException("can't find ID " + ID);//$NON-NLS-1$
        int ix = contributions.indexOf(ci);
        if (ix >= 0) {
            // System.out.println("insert before: " + ix);
            if (allowItem(item)) {
                contributions.add(ix, item);
                itemAdded(item);
            }
        }
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public boolean isDirty() {
        if (isDirty)
            return true;
        if (hasDynamicItems()) {
            for (Iterator iter = contributions.iterator(); iter.hasNext();) {
                IContributionItem item = (IContributionItem) iter.next();
                if (item.isDirty())
                    return true;
            }
        }
        return false;
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public boolean isEmpty() {
        return contributions.isEmpty();
    }

    /**
     * The given item was added to the list of contributions.
     * Marks the manager as dirty and updates the number of dynamic items, and the memento.
     */
    protected void itemAdded(IContributionItem item) {
        item.setParent(this);
        markDirty();
        if (item.isDynamic())
            dynamicItems++;
    }

    /**
     * The given item was removed from the list of contributions.
     * Marks the manager as dirty and updates the number of dynamic items.
     */
    protected void itemRemoved(IContributionItem item) {
        item.setParent(null);
        markDirty();
        if (item.isDynamic())
            dynamicItems--;
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public void markDirty() {
        setDirty(true);
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public void prependToGroup(String groupName, IAction action) {
        addToGroup(groupName, new ActionContributionItem(action), false);
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public void prependToGroup(String groupName, IContributionItem item) {
        addToGroup(groupName, item, false);
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public IContributionItem remove(String ID) {
        IContributionItem ci = find(ID);
        if (ci == null)
            return null;
        return remove(ci);
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public IContributionItem remove(IContributionItem item) {
        if (contributions.remove(item)) {
            itemRemoved(item);
            return item;
        }
        return null;
    }

    /* (non-Javadoc)
     * Method declared on IContributionManager.
     */
    public void removeAll() {
        IContributionItem[] items = getItems();
        contributions.clear();
        for (int i = 0; i < items.length; i++) {
            IContributionItem item = items[i];
            itemRemoved(item);
        }
        dynamicItems = 0;
        markDirty();
    }

    /**
     * Replaces the item of the given identifier with another contribution item.
     * This can be used, for example, to replace large contribution items with
     * placeholders to avoid memory leaks.  If the identifier cannot be found in the
     * current list of items, then this does nothing.  If multiple occurrences are
     * found, then the replacement items is put in the first position and the other
     * positions are removed.
     * @param identifier The identifier to look for in the list of contributions;
     * should not be <code>null</code>.
     * @param replacementItem The contribution item to replace the old item; must
     * not be <code>null</code>.  Use {@link org.eclipse.jface.action.ContributionManager#remove(java.lang.String) remove} if that is what you want to do.
     * @return <code>true</code> if the given identifier can be; <code>
     * @since 3.0
     */
    public boolean replaceItem(final String identifier,
            final IContributionItem replacementItem) {
        if (identifier == null) {
            return false;
        }

        final int index = indexOf(identifier);
        if (index < 0) {
            return false; // couldn't find the item.
        }

        // Remove the old item.
        final IContributionItem oldItem = (IContributionItem) contributions
                .get(index);
        itemRemoved(oldItem);

        // Add the new item.
        contributions.set(index, replacementItem);
        itemAdded(replacementItem); // throws NPE if (replacementItem == null)

        // Go through and remove duplicates.
        for (int i = contributions.size() - 1; i > index; i--) {
            IContributionItem item = (IContributionItem) contributions.get(i);
            if ((item != null) && (identifier.equals(item.getId()))) {
                if (Policy.TRACE_TOOLBAR) {
                    System.out
                            .println("Removing duplicate on replace: " + identifier); //$NON-NLS-1$
                }
                contributions.remove(i);
                itemRemoved(item);
            }
        }

        return true; // success
    }

    /**
     * Sets whether this manager is dirty. When dirty, the list of contributions 
     * is not accurately reflected in the corresponding widgets.
     *
     * @param dirty <code>true</code> if this manager is dirty, and <code>false</code>
     *   if it is up-to-date
     */
    protected void setDirty(boolean dirty) {
        isDirty = dirty;
    }

    /**
     * Sets the overrides for this contribution manager
     * 
     * @param newOverrides the overrides for the items of this manager
     * @since 2.0
     */
    public void setOverrides(IContributionManagerOverrides newOverrides) {
        overrides = newOverrides;
    }

    /**
     * An internal method for setting the order of the contribution items.
     * 
     * @param items the contribution items in the specified order
     * @since 3.0
     */
    protected void internalSetItems(IContributionItem[] items) {
        contributions.clear();
        for (int i = 0; i < items.length; i++) {
            if (allowItem(items[i])) {
                contributions.add(items[i]);
            }
        }
    }
}
