/*******************************************************************************
 * Copyright (c) 2008 Oracle. 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:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.utility.internal.model.value;

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

import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.Transformer;
import org.eclipse.jpt.utility.internal.iterators.ReadOnlyCompositeListIterator;
import org.eclipse.jpt.utility.internal.iterators.TransformationListIterator;
import org.eclipse.jpt.utility.model.event.ListChangeEvent;
import org.eclipse.jpt.utility.model.listener.ListChangeListener;
import org.eclipse.jpt.utility.model.value.ListValueModel;

/**
 * A <code>CompositeListValueModel</code> wraps another
 * <code>ListValueModel</code> and uses a <code>Transformer</code>
 * to convert each item in the wrapped list to yet another
 * <code>ListValueModel</code>. This composite list contains
 * the combined items from all these component lists.
 * 
 * Terminology:
 * - sources - the items in the wrapped list value model; these
 *    are converted into component LVMs by the transformer
 * - componentLVMs - the component list value models that are combined
 *    by this composite list value model
 * - items - the items held by the component LVMs
 */
public class CompositeListValueModel<E1, E2>
	extends ListValueModelWrapper<E1>
	implements ListValueModel<E2>
{
	/**
	 * This is the (optional) user-supplied object that transforms
	 * the items in the wrapped list to list value models.
	 */
	private final Transformer<E1, ListValueModel<E2>> transformer;

	/**
	 * Cache of the sources, component LVMs, lists.
	 */
	private final ArrayList<Info> infoList;
	protected class Info {
		// the object passed to the transformer
		final E1 source;
		// the list value model generated by the transformer
		final ListValueModel<E2> componentLVM;
		// cache of the items held by the component LVM
		final ArrayList<E2> items;
		// the component LVM's beginning index within the composite LVM
		int begin;
		Info(E1 source, ListValueModel<E2> componentLVM, ArrayList<E2> items, int begin) {
			super();
			this.source = source;
			this.componentLVM = componentLVM;
			this.items = items;
			this.begin = begin;
		}
	}

	/** Listener that listens to all the component list value models. */
	private final ListChangeListener componentLVMListener;

	/** Cache the size of the composite list. */
	private int size;


	// ********** constructors **********

	/**
	 * Construct a list value model with the specified wrapped
	 * list value model. Use this constructor if
	 *     - the wrapped list value model already contains other
	 *       list value models or
	 *     - you want to override the <code>transform(E1)</code> method
	 *       instead of building a <code>Transformer</code>
	 */
	public CompositeListValueModel(ListValueModel<? extends E1> listHolder) {
		this(listHolder, Transformer.Null.<E1, ListValueModel<E2>>instance());
	}

	/**
	 * Construct a list value model with the specified wrapped
	 * list value model and transformer.
	 */
	public CompositeListValueModel(ListValueModel<? extends E1> listHolder, Transformer<E1, ListValueModel<E2>> transformer) {
		super(listHolder);
		this.transformer = transformer;
		this.infoList = new ArrayList<Info>();
		this.componentLVMListener = this.buildComponentLVMListener();
		this.size = 0;
	}

	/**
	 * Construct a list value model with the specified, unchanging, wrapped
	 * list. Use this constructor if
	 *     - the wrapped list already contains list value models or
	 *     - you want to override the <code>transform(E1)</code> method
	 *       instead of building a <code>Transformer</code>
	 */
	public CompositeListValueModel(List<? extends E1> list) {
		this(new StaticListValueModel<E1>(list));
	}

	/**
	 * Construct a list value model with the specified, unchanging, wrapped
	 * list and transformer.
	 */
	public CompositeListValueModel(List<? extends E1> list, Transformer<E1, ListValueModel<E2>> transformer) {
		this(new StaticListValueModel<E1>(list), transformer);
	}


	// ********** initialization **********

	protected ListChangeListener buildComponentLVMListener() {
		return new ListChangeListener() {
			public void itemsAdded(ListChangeEvent event) {
				CompositeListValueModel.this.componentItemsAdded(event);
			}		
			public void itemsRemoved(ListChangeEvent event) {
				CompositeListValueModel.this.componentItemsRemoved(event);
			}
			public void itemsReplaced(ListChangeEvent event) {
				CompositeListValueModel.this.componentItemsReplaced(event);
			}
			public void itemsMoved(ListChangeEvent event) {
				CompositeListValueModel.this.componentItemsMoved(event);
			}
			public void listCleared(ListChangeEvent event) {
				CompositeListValueModel.this.componentListCleared(event);
			}
			public void listChanged(ListChangeEvent event) {
				CompositeListValueModel.this.componentListChanged(event);
			}
			@Override
			public String toString() {
				return "component LVM listener";
			}
		};
	}


	// ********** ListValueModel implementation **********

	public E2 get(int index) {
		if ((index < 0) || (index >= this.size)) {
			throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size);
		}
		// move backwards through the info list
		for (int i = this.infoList.size(); i-- > 0; ) {
			Info info = this.infoList.get(i);
			if (index >= info.begin) {
				return info.items.get(index - info.begin);
			}
		}
		throw new IllegalStateException();  // something is wack
	}

	public Iterator<E2> iterator() {
		return this.listIterator();
	}

	public ListIterator<E2> listIterator() {
		return new ReadOnlyCompositeListIterator<E2>(this.buildListsIterators());
	}

	protected ListIterator<ListIterator<E2>> buildListsIterators() {
		return new TransformationListIterator<Info, ListIterator<E2>>(this.infoList.listIterator()) {
			@Override
			protected ListIterator<E2> transform(Info info) {
				return info.items.listIterator();
			}
		};
	}

	public int size() {
		return this.size;
	}

	public Object[] toArray() {
		return CollectionTools.array(this.listIterator(), this.size);
	}


	// ********** ListValueModelWrapper overrides/implementation **********

	@Override
	protected void engageModel() {
		super.engageModel();
		// synch our cache *after* we start listening to the wrapped list,
		// since its value might change when a listener is added
		this.addComponentSources(0, this.listHolder.listIterator(), this.listHolder.size());
	}

	@Override
	protected void disengageModel() {
		super.disengageModel();
		// stop listening to the component LVMs...
		for (Info info : this.infoList) {
			info.componentLVM.removeListChangeListener(LIST_VALUES, this.componentLVMListener);
		}
		// ...and clear the cache
		this.infoList.clear();
		this.size = 0;
	}

	/**
	 * Some component sources were added; update our cache.
	 */
	@Override
	protected void itemsAdded(ListChangeEvent event) {
		this.addComponentSources(event.getIndex(), this.items(event), event.itemsSize(), true);  // true = fire event
	}

	/**
	 * Do not fire an event.
	 */
	protected void addComponentSources(int addedSourcesIndex, ListIterator<? extends E1> addedSources, int addedSourcesSize) {
		this.addComponentSources(addedSourcesIndex, addedSources, addedSourcesSize, false);  // false = do not fire event
	}

	/**
	 * Add infos corresponding to the specified sources to our cache.
	 * Fire the appropriate event if requested.
	 */
	protected void addComponentSources(int addedSourcesIndex, ListIterator<? extends E1> addedSources, int addedSourcesSize, boolean fireEvent) {
		ArrayList<Info> newInfoList = new ArrayList<Info>(addedSourcesSize);
		// the 'items' are either tacked on to the end or
		// at the 'begin' index of the first 'info' that is being pushed back
		int newItemsIndex = (addedSourcesIndex == this.infoList.size()) ? this.size : this.infoList.get(addedSourcesIndex).begin;

		int begin = newItemsIndex;
		while (addedSources.hasNext()) {
			E1 source = addedSources.next();
			ListValueModel<E2> componentLVM = this.transform(source);
			componentLVM.addListChangeListener(LIST_VALUES, this.componentLVMListener);
			ArrayList<E2> items = new ArrayList<E2>(componentLVM.size());
			CollectionTools.addAll(items, componentLVM.listIterator());
			newInfoList.add(new Info(source, componentLVM, items, begin));
			begin += items.size();
		}
		this.infoList.addAll(addedSourcesIndex, newInfoList);
		int newItemsSize = begin - newItemsIndex;
		this.size += newItemsSize;

		// bump the 'begin' index for all the infos that were pushed back by the insert
		int movedInfosIndex = addedSourcesIndex + addedSourcesSize;
		for (int i = movedInfosIndex; i < this.infoList.size(); i++) {
			this.infoList.get(i).begin += newItemsSize;
		}

		if (fireEvent) {
			ArrayList<E2> newItems = new ArrayList<E2>(newItemsSize);
			for (int i = addedSourcesIndex; i < movedInfosIndex; i++) {
				newItems.addAll(this.infoList.get(i).items);
			}
			this.fireItemsAdded(LIST_VALUES, newItemsIndex, newItems);
		}
	}

	/**
	 * Some component sources were removed; update our cache.
	 */
	@Override
	protected void itemsRemoved(ListChangeEvent event) {
		this.removeComponentSources(event.getIndex(), event.itemsSize(), true);  // true = fire event
	}

	/**
	 * Do not fire an event.
	 */
	protected void removeComponentSources(int removedSourcesIndex, int removedSourcesSize) {
		this.removeComponentSources(removedSourcesIndex, removedSourcesSize, false);  // false = do not fire event
	}

	/**
	 * Remove the infos corresponding to the specified sources from our cache.
	 */
	protected void removeComponentSources(int removedSourcesIndex, int removedSourcesSize, boolean fireEvent) {
		int removedItemsIndex = this.infoList.get(removedSourcesIndex).begin;
		int movedSourcesIndex = removedSourcesIndex + removedSourcesSize;
		int movedItemsIndex = (movedSourcesIndex == this.infoList.size()) ? this.size : this.infoList.get(movedSourcesIndex).begin;
		int removedItemsSize = movedItemsIndex - removedItemsIndex;
		this.size -= removedItemsSize;

		List<Info> subList = this.infoList.subList(removedSourcesIndex, removedSourcesIndex + removedSourcesSize);
		ArrayList<Info> removedInfoList = new ArrayList<Info>(subList);  // make a copy
		subList.clear();

		// decrement the 'begin' index for all the infos that were moved forward by the deletes
		for (int i = removedSourcesIndex; i < this.infoList.size(); i++) {
			this.infoList.get(i).begin -= removedItemsSize;
		}

		for (Info removedInfo : removedInfoList) {
			removedInfo.componentLVM.removeListChangeListener(LIST_VALUES, this.componentLVMListener);
		}

		if (fireEvent) {
			ArrayList<E2> removedItems = new ArrayList<E2>(removedItemsSize);
			for (Info removedInfo : removedInfoList) {
				removedItems.addAll(removedInfo.items);
			}
			this.fireItemsRemoved(LIST_VALUES, removedItemsIndex, removedItems);
		}
	}

	/**
	 * Some component sources were replaced; update our cache.
	 */
	@Override
	protected void itemsReplaced(ListChangeEvent event) {
		this.replaceComponentSources(event.getIndex(), this.items(event), event.itemsSize(), true);  // true = fire event
	}

	/**
	 * Replaced component sources will not (typically) map to a set of replaced
	 * items, so we remove and add the corresponding lists of items, resulting in
	 * two events.
	 */
	protected void replaceComponentSources(int replacedSourcesIndex, ListIterator<? extends E1> newSources, int replacedSourcesSize, boolean fireEvent) {
		this.removeComponentSources(replacedSourcesIndex, replacedSourcesSize, fireEvent);
		this.addComponentSources(replacedSourcesIndex, newSources, replacedSourcesSize, fireEvent);
	}

	/**
	 * Some component sources were moved; update our cache.
	 */
	@Override
	protected void itemsMoved(ListChangeEvent event) {
		this.moveComponentSources(event.getTargetIndex(), event.getSourceIndex(), event.getMoveLength(), true);  // true = fire event
	}

	protected void moveComponentSources(int targetSourcesIndex, int sourceSourcesIndex, int movedSourcesLength, boolean fireEvent) {
		int sourceItemsIndex = this.infoList.get(sourceSourcesIndex).begin;

		int nextSourceSourceIndex = sourceSourcesIndex + movedSourcesLength;
		int nextSourceItemIndex = (nextSourceSourceIndex == this.infoList.size()) ? this.size : this.infoList.get(nextSourceSourceIndex).begin;
		int moveItemsLength = nextSourceItemIndex - sourceItemsIndex;

		int targetItemsIndex = -1;
		if (sourceSourcesIndex > targetSourcesIndex) {
			// move from high to low index
			targetItemsIndex = this.infoList.get(targetSourcesIndex).begin;
		} else {
			// move from low to high index (higher items move down during move)
			int nextTargetSourceIndex = targetSourcesIndex + movedSourcesLength;
			targetItemsIndex = (nextTargetSourceIndex == this.infoList.size()) ? this.size : this.infoList.get(nextTargetSourceIndex).begin;
			targetItemsIndex = targetItemsIndex - moveItemsLength;
		}

		CollectionTools.move(this.infoList, targetSourcesIndex, sourceSourcesIndex, movedSourcesLength);

		// update the 'begin' indexes of all the affected 'infos'
		int min = Math.min(targetSourcesIndex, sourceSourcesIndex);
		int max = Math.max(targetSourcesIndex, sourceSourcesIndex) + movedSourcesLength;
		int begin = Math.min(targetItemsIndex, sourceItemsIndex);
		for (int i = min; i < max; i++) {
			Info info = this.infoList.get(i);
			info.begin = begin;
			begin += info.componentLVM.size();
		}

		if (fireEvent) {
			this.fireItemsMoved(LIST_VALUES, targetItemsIndex, sourceItemsIndex, moveItemsLength);
		}
	}

	/**
	 * The component sources were cleared; clear our cache.
	 */
	@Override
	protected void listCleared(ListChangeEvent event) {
		this.removeComponentSources(0, this.infoList.size());
		this.fireListCleared(LIST_VALUES);
	}

	/**
	 * The component sources changed; rebuild our cache.
	 */
	@Override
	protected void listChanged(ListChangeEvent event) {
		this.removeComponentSources(0, this.infoList.size());
		this.addComponentSources(0, this.listHolder.listIterator(), this.listHolder.size());
		this.fireListChanged(LIST_VALUES);
	}

	@Override
	public void toString(StringBuilder sb) {
		sb.append(CollectionTools.list(this.listIterator(), this.size));
	}


	// ********** internal methods **********

	/**
	 * Transform the specified object into a list value model.
	 * <p>
	 * This method can be overridden by a subclass as an
	 * alternative to building a <code>Transformer</code>.
	 */
	protected ListValueModel<E2> transform(E1 value) {
		return this.transformer.transform(value);
	}

	/**
	 * Return the index of the specified component LVM.
	 */
	protected int indexOf(ListValueModel<E2> componentLVM) {
		for (int i = 0; i < this.infoList.size(); i++) {
			if (this.infoList.get(i).componentLVM == componentLVM) {
				return i;
			}
		}
		throw new IllegalArgumentException("invalid component LVM: " + componentLVM);
	}

	/**
	 * Return the index of the specified event's component LVM.
	 */
	protected int indexFor(ListChangeEvent event) {
		return this.indexOf(this.componentLVM(event));
	}

	/**
	 * Items were added to one of the component lists;
	 * synchronize our cache.
	 */
	protected void componentItemsAdded(ListChangeEvent event) {
		// update the affected 'begin' indices
		int componentLVMIndex = this.indexFor(event);
		int newItemsSize = event.itemsSize();
		for (int i = componentLVMIndex + 1; i < this.infoList.size(); i++) {
			this.infoList.get(i).begin += newItemsSize;
		}
		this.size += newItemsSize;

		// synchronize the cached list
		Info info = this.infoList.get(componentLVMIndex);
		CollectionTools.addAll(info.items, event.getIndex(), this.componentItems(event), event.itemsSize());

		// translate the event
		this.fireItemsAdded(event.cloneWithSource(this, LIST_VALUES, info.begin));
	}

	/**
	 * Items were removed from one of the component lists;
	 * synchronize our cache.
	 */
	protected void componentItemsRemoved(ListChangeEvent event) {
		// update the affected 'begin' indices
		int componentLVMIndex = this.indexFor(event);
		int removedItemsSize = event.itemsSize();
		for (int i = componentLVMIndex + 1; i < this.infoList.size(); i++) {
			this.infoList.get(i).begin -= removedItemsSize;
		}
		this.size -= removedItemsSize;

		// synchronize the cached list
		Info info = this.infoList.get(componentLVMIndex);
		int itemIndex = event.getIndex();
		info.items.subList(itemIndex, itemIndex + event.itemsSize()).clear();

		// translate the event
		this.fireItemsRemoved(event.cloneWithSource(this, LIST_VALUES, info.begin));
	}

	/**
	 * Items were replaced in one of the component lists;
	 * synchronize our cache.
	 */
	protected void componentItemsReplaced(ListChangeEvent event) {
		// no changes to the 'begin' indices or size

		// synchronize the cached list
		int componentLVMIndex = this.indexFor(event);
		Info info = this.infoList.get(componentLVMIndex);
		int i = event.getIndex();
		for (Iterator<E2> stream = this.componentItems(event); stream.hasNext(); ) {
			info.items.set(i++, stream.next());
		}

		// translate the event
		this.fireItemsReplaced(event.cloneWithSource(this, LIST_VALUES, info.begin));
	}

	/**
	 * Items were moved in one of the component lists;
	 * synchronize our cache.
	 */
	protected void componentItemsMoved(ListChangeEvent event) {
		// no changes to the 'begin' indices or size

		// synchronize the cached list
		int componentLVMIndex = this.indexFor(event);
		Info info = this.infoList.get(componentLVMIndex);
		CollectionTools.move(info.items, event.getTargetIndex(), event.getSourceIndex(), event.getMoveLength());

		// translate the event
		this.fireItemsMoved(event.cloneWithSource(this, LIST_VALUES, info.begin));
	}

	/**
	 * One of the component lists was cleared;
	 * synchronize our cache.
	 */
	protected void componentListCleared(ListChangeEvent event) {
		int componentLVMIndex = this.indexFor(event);
		this.clearComponentList(componentLVMIndex, this.infoList.get(componentLVMIndex));
	}

	protected void clearComponentList(int componentLVMIndex, Info info) {
		// update the affected 'begin' indices
		int removedItemsSize = info.items.size();
		for (int i = componentLVMIndex + 1; i < this.infoList.size(); i++) {
			this.infoList.get(i).begin -= removedItemsSize;
		}
		this.size -= removedItemsSize;

		// synchronize the cached list
		ArrayList<E2> items = new ArrayList<E2>(info.items);
		info.items.clear();

		// translate the event
		this.fireItemsRemoved(LIST_VALUES, info.begin, items);
	}

	/**
	 * One of the component lists changed;
	 * synchronize our cache by clearing out the appropriate
	 * list and rebuilding it.
	 */
	protected void componentListChanged(ListChangeEvent event) {
		int componentLVMIndex = this.indexFor(event);
		Info info = this.infoList.get(componentLVMIndex);
		this.clearComponentList(componentLVMIndex, info);

		// update the affected 'begin' indices
		int newItemsSize = info.componentLVM.size();
		for (int i = componentLVMIndex + 1; i < this.infoList.size(); i++) {
			this.infoList.get(i).begin += newItemsSize;
		}
		this.size += newItemsSize;

		// synchronize the cached list
		CollectionTools.addAll(info.items, info.componentLVM.listIterator(), newItemsSize);

		// translate the event
		this.fireItemsAdded(LIST_VALUES, info.begin, info.items);
	}

	// minimize scope of suppressed warnings
	@SuppressWarnings("unchecked")
	protected ListIterator<E2> componentItems(ListChangeEvent event) {
		return (ListIterator<E2>) event.items();
	}

	// minimize scope of suppressed warnings
	@SuppressWarnings("unchecked")
	protected ListValueModel<E2> componentLVM(ListChangeEvent event) {
		return (ListValueModel<E2>) event.getSource();
	}

}
