package org.eclipse.ui.internal;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */

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

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.CoolBar;
import org.eclipse.swt.widgets.CoolItem;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.PlatformUI;

public class CoolBarLayout {
	public Point[] itemSizes = new Point[0];
	public int[] itemWrapIndices = new int[0];

	// the coolbar contribution items in order of display
	// store the item id instead of indexes because the coolbar
	// items may change between saving/restoring
	ArrayList items = new ArrayList(0);

	ArrayList rememberedPositions = new ArrayList();

	public CoolBarLayout() {
	}
	public CoolBarLayout(CoolBar coolBar) {
		this();
		initialize(coolBar);
	}
	void initialize(CoolBar coolBar) {
		CoolItem[] coolItems = coolBar.getItems();
		ArrayList newItems = new ArrayList(coolItems.length);
		for (int i = 0; i < coolItems.length; i++) {
			CoolBarContributionItem item = (CoolBarContributionItem) coolItems[i].getData();
			if (item != null) {
				newItems.add(item.getId());
			}
		}
		items = newItems;
		itemSizes = coolBar.getItemSizes();
		itemWrapIndices = getAdjustedWrapIndices(coolBar.getWrapIndices());
	
		// Save the preferred size as actual size for the last item on a row
		int count = coolBar.getItemCount();
		int[] lastIndices = coolBar.getWrapIndices();
		int n = lastIndices.length;
		if (n == 0) {
			if (count == 0) lastIndices = new int[0];
			else lastIndices = new int[] {count - 1};
		} else {
			// convert from first item indices to last item indices
			for (int i = 0; i < n - 1; ++i) {
				lastIndices[i] = lastIndices[i+1] - 1;
			}
			lastIndices[n - 1] = count - 1;
		}
		for (int i = 0; i < lastIndices.length; i++) {
			int lastIndex = lastIndices[i];
			if (lastIndex >= 0 && lastIndex < coolItems.length) {
				CoolItem lastItem = coolItems[lastIndex];
				itemSizes[lastIndex] = lastItem.getPreferredSize();
			}
		}
	}
	public CoolBarLayout(ArrayList items, int[] itemWrapIndices, Point[] itemSizes, ArrayList rememberedPositions) {
		this.items = items;
		this.itemWrapIndices = itemWrapIndices;
		this.itemSizes = itemSizes;
		this.rememberedPositions = rememberedPositions;
	}
	/**
	 * Return the set of wrap indices that would be a result of adding
	 * an item at the given itemIndex on the the given row.
	 */
	int[] wrapsForNewItem(int rowIndex, int itemIndex) {
		int[] newWraps = null;
		int rowStartIndex = getStartIndexOfRow(rowIndex);
		if (itemIndex == rowStartIndex) {
			// if itemIndex is the start of the row, we are adding the item 
			// to the beginning of the row, so adjust the wrap indices
			newWraps = new int[itemWrapIndices.length];
			System.arraycopy(itemWrapIndices, 0, newWraps, 0, itemWrapIndices.length);
			newWraps[rowIndex] = itemIndex;
			for (int i = rowIndex + 1; i < newWraps.length; i++) {
				newWraps[i]++;
			}
		} 
		return newWraps;
	}
	/**
	 * Return the set of wrap indices that would be a result of adding
	 * an item at the given itemIndex on the given new row.
	 */
	int[]  wrapsForNewRow(int rowIndex, int itemIndex) {
		int[] newWraps = new int[itemWrapIndices.length + 1];
		for (int j = 0; j < rowIndex; j++) {
			newWraps[j]=itemWrapIndices[j];
		}
		newWraps[rowIndex] = itemIndex;
		for (int j = rowIndex; j < itemWrapIndices.length; j++) {
			newWraps[j+1]=itemWrapIndices[j]+1;
		}
		return newWraps;
	}
	/** 
	 * Return a consistent set of wrap indices.  The return value
	 * will always include at least one entry and the first entry will 
	 * always be zero.  CoolBar.getWrapIndices() is inconsistent 
	 * in whether or not it returns an index for the first row.
	 */
	private int[] getAdjustedWrapIndices(int[] wraps) {
		int[] adjustedWrapIndices;
		if (wraps.length == 0) {
			adjustedWrapIndices = new int[] { 0 };
		} else {
			if (wraps[0] != 0) {
				adjustedWrapIndices = new int[wraps.length + 1];
				adjustedWrapIndices[0] = 0;
				for (int i = 0; i < wraps.length; i++) {
					adjustedWrapIndices[i + 1] = wraps[i];
				}
			} else {
				adjustedWrapIndices = wraps;
			}
		}
		return adjustedWrapIndices;
	}
	/** 
	 * Return the number of rows in the layout.
	 */
	int getNumberOfRows() {
		return itemWrapIndices.length;
	}
	/**
	 */
	int getRowOfIndex(int index) {
		int row = -1;
		for (row = 0; row < itemWrapIndices.length; row++) {
			if (itemWrapIndices[row] > index) break;
		}
		if (row > 0) row--;
		return row;
	}
	/**
	 * Return the item index of the first item on the given row.
	 */
	int getStartIndexOfRow(int rowIndex) {
		// return the item index of the first item in the given row
		if (rowIndex > itemWrapIndices.length - 1) return -1;  // row doesn't exist
		return itemWrapIndices[rowIndex];
	}
	boolean isOnRowAlone(int itemIndex) {
		int row = getRowOfIndex(itemIndex);
		int rowStart = getStartIndexOfRow(row);
		int nextRowStart = getStartIndexOfRow(row + 1);
		if (nextRowStart == -1) nextRowStart = rowStart;
		return (rowStart == itemIndex) && (nextRowStart - rowStart <= 1);
	}
	/**
	 * Return whether or not the items from this layout that are in
	 * otherLayout are in the same order within the layouts.
	 */
	/* package */ boolean isDerivativeOf(CoolBarLayout otherLayout) {
		// for the items that are in this layout, 
		// get the indexes of these items in otherLayout
		ArrayList indexes = new ArrayList();
		for (int i=0; i<this.items.size(); i++) {
			String itemId = (String)this.items.get(i);
			int index = otherLayout.items.indexOf(itemId);
			if (index != -1) indexes.add(new Integer(index));
		}
		// see if the items that are shared across the two
		// layouts are in the same order, if not return 
		// false
		int previous = -1;
		for (int i=0; i<indexes.size(); i++) {
			int value = ((Integer)indexes.get(i)).intValue();
			if (value > previous) {
				previous = value;
			} else {
				return false;
			}
		}
		return true;
	}
	/**
	 * Restores the object state in the given memento. Returns whether or not the
	 * restoration was successful.
	 * 
	 * @param memento the memento to save the object state in
	 */
	public boolean restoreState(IMemento memento) {
		IMemento [] sizes = memento.getChildren(IWorkbenchConstants.TAG_ITEM_SIZE);
		if (sizes == null) return false;
		itemSizes = new Point[sizes.length];
		for (int i = 0; i < sizes.length; i++) {
			IMemento sizeMem = sizes[i];
			Integer x = sizeMem.getInteger(IWorkbenchConstants.TAG_X);
			if (x == null) return false;
			Integer y = sizeMem.getInteger(IWorkbenchConstants.TAG_Y);
			if (y == null) return false;
			itemSizes[i] = new Point(x.intValue(), y.intValue());
		}
		IMemento [] wraps = memento.getChildren(IWorkbenchConstants.TAG_ITEM_WRAP_INDEX);
		if (wraps == null) return false;
		itemWrapIndices = new int[wraps.length];
		for (int i = 0; i < wraps.length; i++) {
			IMemento wrapMem = wraps[i];
			Integer index = wrapMem.getInteger(IWorkbenchConstants.TAG_INDEX);
			if (index == null) return false;
			itemWrapIndices[i] = index.intValue();
		}
		IMemento [] savedItems = memento.getChildren(IWorkbenchConstants.TAG_ITEM);
		if (savedItems == null) return false;
		items = new ArrayList(savedItems.length);
		for (int i = 0; i < savedItems.length; i++) {
			IMemento savedMem = savedItems[i];
			String id = savedMem.getString(IWorkbenchConstants.TAG_ID);
			if (id == null) return false;
			items.add(id);
		}
		IMemento [] savedPositions = memento.getChildren(IWorkbenchConstants.TAG_POSITION);
		rememberedPositions = new ArrayList(savedPositions.length);
		for (int i=0; i < savedPositions.length; i++) {
			CoolItemPosition position = new CoolItemPosition();
			IMemento savedPos = savedPositions[i];
			position.id = savedPos.getString(IWorkbenchConstants.TAG_ID);
			if (position.id == null) return false;
			Integer pos = savedPos.getInteger(IWorkbenchConstants.TAG_ADDED);
			if (pos == null) return false;
			int added = pos.intValue();
			position.added = added == 1;
			position.layout = new CoolBarLayout();
			IMemento layoutMemento = savedPos.getChild(IWorkbenchConstants.TAG_LAYOUT);
			if (layoutMemento == null) return false;
			position.layout.restoreState(layoutMemento);
			rememberedPositions.add(position);
		}
		return true;	
	}
	/**
	 * Saves the object state in the given memento. 
	 * 
	 * @param memento the memento to save the object state in
	 */
	public IStatus saveState(IMemento memento) {
		for (int i = 0; i < itemSizes.length; i++) {
			IMemento child = memento.createChild(IWorkbenchConstants.TAG_ITEM_SIZE);
			Point pt = itemSizes[i];
			child.putInteger(IWorkbenchConstants.TAG_X, pt.x);
			child.putInteger(IWorkbenchConstants.TAG_Y, pt.y);
		}
		for (int i = 0; i < itemWrapIndices.length; i++) {
			IMemento child = memento.createChild(IWorkbenchConstants.TAG_ITEM_WRAP_INDEX);
			child.putInteger(IWorkbenchConstants.TAG_INDEX, itemWrapIndices[i]);
		}
		Iterator iter = items.iterator();
		while (iter.hasNext()) {
			IMemento child = memento.createChild(IWorkbenchConstants.TAG_ITEM);
			String item = (String)iter.next();
			child.putString(IWorkbenchConstants.TAG_ID, item);
		}
		iter = rememberedPositions.iterator();
		while (iter.hasNext()) {
			IMemento child = memento.createChild(IWorkbenchConstants.TAG_POSITION);
			CoolItemPosition position = (CoolItemPosition)iter.next();
			child.putString(IWorkbenchConstants.TAG_ID, position.id);
			int value = 0;
			if (position.added) value = 1;
			child.putInteger(IWorkbenchConstants.TAG_ADDED, value);
			IMemento layout = child.createChild(IWorkbenchConstants.TAG_LAYOUT);
			position.layout.saveState(layout); 
		}
		return new Status(IStatus.OK,PlatformUI.PLUGIN_ID,0,"",null);
	}
	public String toString() {
		StringBuffer buffer = new StringBuffer(20);
		buffer.append("items "); //$NON-NLS-1$
		for (int i = 0; i < items.size(); i++) {
			String item = (String)items.get(i);
			buffer.append(item + " ");
		}
		buffer.append('\n');
		buffer.append("item wrap indices "); //$NON-NLS-1$
		for (int i = 0; i < itemWrapIndices.length; i++) {
			buffer.append(itemWrapIndices[i] + " "); //$NON-NLS-1$
		}
		buffer.append('\n');
		buffer.append("item sizes "); //$NON-NLS-1$
		for (int i = 0; i < itemSizes.length; i++) {
			buffer.append(itemSizes[i] + " "); //$NON-NLS-1$
		}
		buffer.append('\n');
		return buffer.toString();
	}
}