/*******************************************************************************
 * Copyright (c) 2007, 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.Collection;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.NullList;
import org.eclipse.jpt.utility.internal.Transformer;
import org.eclipse.jpt.utility.internal.iterators.CompositeIterator;
import org.eclipse.jpt.utility.internal.iterators.TransformationIterator;
import org.eclipse.jpt.utility.model.event.CollectionChangeEvent;
import org.eclipse.jpt.utility.model.listener.CollectionChangeListener;
import org.eclipse.jpt.utility.model.value.CollectionValueModel;
import org.eclipse.jpt.utility.model.value.ListValueModel;

/**
 * A <code>CompositeCollectionValueModel</code> wraps another
 * <code>CollectionValueModel</code> and uses a <code>Transformer</code>
 * to convert each item in the wrapped collection to yet another
 * <code>CollectionValueModel</code>. This composite collection contains
 * the combined items from all these component collections.
 * 
 * NB: The wrapped collection must be an "identity set" that does not
 * contain the same item twice or this class will throw an exception.
 * 
 * Terminology:
 * - sources - the items in the wrapped collection value model; these
 *    are converted into component CVMs by the transformer
 * - component CVMs - the component collection value models that are combined
 *    by this composite collection value model
 * - items - the items held by the component CVMs
 */
public class CompositeCollectionValueModel<E1, E2>
	extends CollectionValueModelWrapper<E1>
	implements CollectionValueModel<E2>
{
	/**
	 * This is the (optional) user-supplied object that transforms
	 * the items in the wrapped collection to collection value models.
	 */
	private final Transformer<E1, CollectionValueModel<E2>> transformer;

	/**
	 * Cache of the component collection value models that
	 * were generated by the transformer; keyed by the item
	 * in the wrapped collection that was passed to the transformer.
	 */
	private final IdentityHashMap<E1, CollectionValueModel<E2>> componentCVMs;

	/**
	 * Cache of the collections corresponding to the component
	 * collection value models above; keyed by the component
	 * collection value models.
	 * Use ArrayLists so we can use ArrayList-specific methods
	 * (e.g. #clone() and #ensureCapacity()).
	 */
	private final IdentityHashMap<CollectionValueModel<E2>, ArrayList<E2>> collections;

	/** Listener that listens to all the component collection value models. */
	private final CollectionChangeListener componentCVMListener;

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


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

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

	/**
	 * Construct a collection value model with the specified wrapped
	 * collection value model and transformer.
	 */
	public CompositeCollectionValueModel(CollectionValueModel<? extends E1> collectionHolder, Transformer<E1, CollectionValueModel<E2>> transformer) {
		super(collectionHolder);
		this.transformer = transformer;
		this.componentCVMs = new IdentityHashMap<E1, CollectionValueModel<E2>>();
		this.collections = new IdentityHashMap<CollectionValueModel<E2>, ArrayList<E2>>();
		this.componentCVMListener = this.buildComponentListener();
		this.size = 0;
	}

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

	/**
	 * Construct a collection value model with the specified wrapped
	 * list value model and transformer.
	 */
	public CompositeCollectionValueModel(ListValueModel<? extends E1> listHolder, Transformer<E1, CollectionValueModel<E2>> transformer) {
		this(new ListCollectionValueModelAdapter<E1>(listHolder), transformer);
	}

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

	/**
	 * Construct a collection value model with the specified, unchanging, wrapped
	 * collection and transformer.
	 */
	public CompositeCollectionValueModel(Collection<? extends E1> collection, Transformer<E1, CollectionValueModel<E2>> transformer) {
		this(new StaticCollectionValueModel<E1>(collection), transformer);
	}


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

	protected CollectionChangeListener buildComponentListener() {
		return new CollectionChangeListener() {
			public void itemsAdded(CollectionChangeEvent event) {
				CompositeCollectionValueModel.this.componentItemsAdded(event);
			}		
			public void itemsRemoved(CollectionChangeEvent event) {
				CompositeCollectionValueModel.this.componentItemsRemoved(event);
			}
			public void collectionCleared(CollectionChangeEvent event) {
				CompositeCollectionValueModel.this.componentCollectionCleared(event);
			}
			public void collectionChanged(CollectionChangeEvent event) {
				CompositeCollectionValueModel.this.componentCollectionChanged(event);
			}
			@Override
			public String toString() {
				return "component listener";
			}
		};
	}


	// ********** CollectionValueModel implementation **********

	public Iterator<E2> iterator() {
		return new CompositeIterator<E2>(this.buildCollectionsIterators());
	}

	protected Iterator<Iterator<E2>> buildCollectionsIterators() {
		return new TransformationIterator<ArrayList<E2>, Iterator<E2>>(this.collections.values().iterator()) {
			@Override
			protected Iterator<E2> transform(ArrayList<E2> next) {
				return next.iterator();
			}
		};
	}

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


	// ********** CollectionValueModelWrapper overrides/implementation **********

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

	/**
	 * Transform all the sources to collection value models
	 * and add their items to our cache, with no event notification.
	 */
	protected void addAllComponentSources() {
		for (E1 source : this.collectionHolder) {
			this.addComponentSource(source, NullList.<E2>instance());
		}
	}

	@Override
	protected void disengageModel() {
		super.disengageModel();
		// stop listening to the components...
		for (CollectionValueModel<E2> componentCVM : this.componentCVMs.values()) {
			componentCVM.removeCollectionChangeListener(VALUES, this.componentCVMListener);
		}
		// ...and clear the cache
		this.componentCVMs.clear();
		this.collections.clear();
		this.size = 0;
	}

	/**
	 * Some component sources were added;
	 * add their corresponding items to our cache.
	 */
	@Override
	protected void itemsAdded(CollectionChangeEvent event) {
		ArrayList<E2> addedItems = new ArrayList<E2>();
		for (Iterator<E1> stream = this.items(event); stream.hasNext(); ) {
			this.addComponentSource(stream.next(), addedItems);
		}
		this.fireItemsAdded(VALUES, addedItems);
	}

	/**
	 * Transform the specified source to a collection value model
	 * and add its items to our cache and the "collecting parameter".
	 */
	protected void addComponentSource(E1 source, List<E2> addedItems) {
		CollectionValueModel<E2> componentCVM = this.transform(source);
		if (this.componentCVMs.put(source, componentCVM) != null) {
			throw new IllegalStateException("duplicate component: " + source);
		}
		componentCVM.addCollectionChangeListener(VALUES, this.componentCVMListener);
		ArrayList<E2> componentCollection = new ArrayList<E2>(componentCVM.size());
		if (this.collections.put(componentCVM, componentCollection) != null) {
			throw new IllegalStateException("duplicate collection: " + source);
		}
		this.addComponentItems(componentCVM, componentCollection);
		addedItems.addAll(componentCollection);
	}

	/**
	 * Add the items in the specified component CVM to the specified component
	 * collection.
	 */
	protected void addComponentItems(CollectionValueModel<E2> componentCVM, ArrayList<E2> componentCollection) {
		int itemsSize = componentCVM.size();
		this.size += itemsSize;
		componentCollection.ensureCapacity(componentCollection.size() + itemsSize);
		CollectionTools.addAll(componentCollection, componentCVM);
	}

	/**
	 * Some component sources were removed;
	 * remove their corresponding items from our cache.
	 */
	@Override
	protected void itemsRemoved(CollectionChangeEvent event) {
		ArrayList<E2> removedItems = new ArrayList<E2>();
		for (Iterator<E1> stream = this.items(event); stream.hasNext(); ) {
			this.removeComponentSource(stream.next(), removedItems);
		}
		this.fireItemsRemoved(VALUES, removedItems);
	}

	/**
	 * Remove the items corresponding to the specified source
	 * from our cache.
	 */
	protected void removeComponentSource(E1 source, List<E2> removedItems) {
		CollectionValueModel<E2> componentCVM = this.componentCVMs.remove(source);
		if (componentCVM == null) {
			throw new IllegalStateException("missing component: " + source);
		}
		componentCVM.removeCollectionChangeListener(VALUES, this.componentCVMListener);
		ArrayList<E2> componentCollection = this.collections.remove(componentCVM);
		if (componentCollection == null) {
			throw new IllegalStateException("missing collection: " + source);
		}
		removedItems.addAll(componentCollection);
		this.removeComponentItems(componentCollection);
	}

	/**
	 * Update our size and collection cache.
	 */
	protected void removeComponentItems(ArrayList<E2> componentCollection) {
		this.size -= componentCollection.size();
		componentCollection.clear();
	}

	/**
	 * The component sources cleared;
	 * clear our cache.
	 */
	@Override
	protected void collectionCleared(CollectionChangeEvent event) {
		this.removeAllComponentSources();
		this.fireCollectionCleared(VALUES);
	}

	protected void removeAllComponentSources() {
		// copy the keys so we don't eat our own tail
		ArrayList<E1> copy = new ArrayList<E1>(this.componentCVMs.keySet());
		for (E1 source : copy) {
			this.removeComponentSource(source, NullList.<E2>instance());
		}
	}

	/**
	 * The component sources changed;
	 * rebuild our cache.
	 */
	@Override
	protected void collectionChanged(CollectionChangeEvent event) {
		this.removeAllComponentSources();
		this.addAllComponentSources();
		this.fireCollectionChanged(VALUES);
	}


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

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

	/**
	 * One of the component collections had items added;
	 * synchronize our caches.
	 */
	protected void componentItemsAdded(CollectionChangeEvent event) {
		int itemsSize = event.itemsSize();
		this.size += itemsSize;

		ArrayList<E2> componentCollection = this.collections.get(this.componentCVM(event));
		componentCollection.ensureCapacity(componentCollection.size() + itemsSize);

		this.addItemsToCollection(this.componentItems(event), componentCollection, VALUES);
	}

	/**
	 * One of the component collections had items removed;
	 * synchronize our caches.
	 */
	protected void componentItemsRemoved(CollectionChangeEvent event) {
		this.size -= event.itemsSize();
		ArrayList<E2> componentCollection = this.collections.get(this.componentCVM(event));
		this.removeItemsFromCollection(this.componentItems(event), componentCollection, VALUES);
	}

	/**
	 * One of the component collections was cleared;
	 * synchronize our caches by clearing out the appropriate
	 * collection.
	 */
	protected void componentCollectionCleared(CollectionChangeEvent event) {
		ArrayList<E2> componentCollection = this.collections.get(this.componentCVM(event));
		ArrayList<E2> removedItems = new ArrayList<E2>(componentCollection);
		this.removeComponentItems(componentCollection);
		this.fireItemsRemoved(VALUES, removedItems);
	}

	/**
	 * One of the component collections changed;
	 * synchronize our caches by clearing out the appropriate
	 * collection and then rebuilding it.
	 */
	protected void componentCollectionChanged(CollectionChangeEvent event) {
		CollectionValueModel<E2> componentCVM = this.componentCVM(event);
		ArrayList<E2> componentCollection = this.collections.get(componentCVM);
		this.removeComponentItems(componentCollection);
		this.addComponentItems(componentCVM, componentCollection);
		this.fireCollectionChanged(VALUES);
	}

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

	// minimize scope of suppressed warnings
	@SuppressWarnings("unchecked")
	protected CollectionValueModel<E2> componentCVM(CollectionChangeEvent event) {
		return (CollectionValueModel<E2>) event.getSource();
	}

}
