/*******************************************************************************
 * Copyright (c) 2007, 2012 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.jpa.core.internal;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jpt.common.core.internal.utility.PlatformTools;
import org.eclipse.jpt.common.core.internal.utility.jdt.JDTModifiedDeclaration.Adapter;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.common.utility.internal.Tools;
import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable;
import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
import org.eclipse.jpt.common.utility.internal.iterators.CloneIterator;
import org.eclipse.jpt.common.utility.internal.model.AbstractModel;
import org.eclipse.jpt.common.utility.internal.model.AspectChangeSupport;
import org.eclipse.jpt.common.utility.internal.model.ChangeSupport;
import org.eclipse.jpt.jpa.core.JpaDataSource;
import org.eclipse.jpt.jpa.core.JpaFactory;
import org.eclipse.jpt.jpa.core.JpaFile;
import org.eclipse.jpt.jpa.core.JpaNode;
import org.eclipse.jpt.jpa.core.JpaPlatform;
import org.eclipse.jpt.jpa.core.JpaPlatformVariation;
import org.eclipse.jpt.jpa.core.JpaProject;
import org.eclipse.jpt.jpa.core.JptJpaCorePlugin;
import org.eclipse.jpt.jpa.core.context.JpaContextNode;
import org.eclipse.jpt.jpa.core.jpa2.JpaFactory2_0;
import org.eclipse.jpt.jpa.db.Catalog;
import org.eclipse.jpt.jpa.db.Database;

/**
 * Some common Dali behavior:<ul>
 * <li>containment hierarchy
 * <li>Eclipse adaptable
 * <li>update triggers
 * </ul>
 */
public abstract class AbstractJpaNode
	extends AbstractModel
	implements JpaNode
{
	protected final JpaNode parent;


	// ********** constructor/initialization **********

	protected AbstractJpaNode(JpaNode parent) {
		super();
		this.checkParent(parent);
		this.parent = parent;
	}

	protected void checkParent(JpaNode p) {
		if (p == null) {
			if (this.requiresParent()) {
				throw new IllegalArgumentException("'parent' cannot be null"); //$NON-NLS-1$
			}
		} else {
			if (this.forbidsParent()) {
				throw new IllegalArgumentException("'parent' must be null"); //$NON-NLS-1$
			}
		}
	}

	protected boolean requiresParent() {
		return true;
	}

	protected final boolean forbidsParent() {
		return ! this.requiresParent();  // assume 'parent' is not optional
	}

	@Override
	protected ChangeSupport buildChangeSupport() {
		return new AspectChangeSupport(this, this.buildChangeSupportListener());
	}

	protected AspectChangeSupport.Listener buildChangeSupportListener() {
		return new AspectChangeSupport.Listener() {
			public void aspectChanged(String aspectName) {
				AbstractJpaNode.this.aspectChanged(aspectName);
			}
		};
	}


	// ********** IAdaptable implementation **********

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Object getAdapter(Class adapter) {
		return PlatformTools.getAdapter(this, adapter);
	}


	// ********** JpaNode implementation **********

	public JpaNode getParent() {
		return this.parent;
	}

	public IResource getResource() {
		return this.parent.getResource();
	}

	/**
	 * @see AbstractJpaProject#getJpaProject()
	 */
	public JpaProject getJpaProject() {
		return this.parent.getJpaProject();
	}

	public JpaProject.Manager getJpaProjectManager() {
		return this.getJpaProject().getManager();
	}


	// ********** convenience methods **********

	protected IJavaProject getJavaProject() {
		return this.getJpaProject().getJavaProject();
	}

	/**
	 * This is <code>public</code> as a convenience because various subclasses
	 * implement interfaces that require this method.
	 */
	public JpaPlatform getJpaPlatform() {
		return this.getJpaProject().getJpaPlatform();
	}
	
	protected JpaPlatform.Version getJpaPlatformVersion() {
		return this.getJpaPlatform().getJpaVersion();
	}

	protected boolean isJpa2_0Compatible() {
		return JptJpaCorePlugin.nodeIsJpa2_0Compatible(this);
	}

	/**
	 * Call {@link #isJpa2_0Compatible()} before calling this method.
	 */
	protected JpaFactory2_0 getJpaFactory2_0() {
		return (JpaFactory2_0) this.getJpaFactory();
	}

	protected JpaFactory getJpaFactory() {
		return this.getJpaPlatform().getJpaFactory();
	}

	protected JpaPlatformVariation getJpaPlatformVariation() {
		return this.getJpaPlatform().getJpaVariation();
	}

	protected JpaFile getJpaFile(IFile file) {
		return this.getJpaProject().getJpaFile(file);
	}

	protected JpaDataSource getDataSource() {
		return this.getJpaProject().getDataSource();
	}

	protected Database getDatabase() {
		return this.getDataSource().getDatabase();
	}

	protected boolean connectionProfileIsActive() {
		return this.getDataSource().connectionProfileIsActive();
	}

	/**
	 * Pre-condition: specified catalog <em>identifier</em> is not
	 * <code>null</code>.
	 * <p>
	 * <strong>NB:</strong> Do not use the catalog <em>name</em>.
	 */
	protected Catalog resolveDbCatalog(String catalog) {
		Database database = this.getDatabase();
		return (database == null) ? null : database.getCatalogForIdentifier(catalog);
	}


	// ********** logging **********

	/**
	 * Log the specified message.
	 */
	protected void log(String msg) {
		this.getJpaProjectManager().log(msg);
	}

	/**
	 * Log the specified exception/error.
	 */
	protected void log(Throwable throwable) {
		this.getJpaProjectManager().log(throwable);
	}

	/**
	 * Log the specified message and exception/error.
	 */
	protected void log(String msg, Throwable throwable) {
		this.getJpaProjectManager().log(msg, throwable);
	}


	// ********** AspectChangeSupport.Listener support **********

	protected void aspectChanged(String aspectName) {
		if (this.aspectTriggersUpdate(aspectName)) {
//			String msg = Thread.currentThread() + " aspect change: " + this + ": " + aspectName;
//			System.out.println(msg);
//			new Exception(msg).printStackTrace(System.out);
			this.stateChanged();
		}
	}

	protected boolean aspectTriggersUpdate(String aspectName) {
		return ! this.aspectDoesNotTriggerUpdate(aspectName);
	}

	protected boolean aspectDoesNotTriggerUpdate(String aspectName) {
		// ignore state changes so we don't get a stack overflow :-)
		// (and we don't use state changes except here)
		return (aspectName == null) ||
				this.nonUpdateAspectNames().contains(aspectName);
	}

	protected final Set<String> nonUpdateAspectNames() {
		synchronized (NON_UPDATE_ASPECT_NAME_SETS) {
			HashSet<String> nonUpdateAspectNames = NON_UPDATE_ASPECT_NAME_SETS.get(this.getClass());
			if (nonUpdateAspectNames == null) {
				nonUpdateAspectNames = new HashSet<String>();
				this.addNonUpdateAspectNamesTo(nonUpdateAspectNames);
				NON_UPDATE_ASPECT_NAME_SETS.put(this.getClass(), nonUpdateAspectNames);
			}
			return nonUpdateAspectNames;
		}
	}

	private static final HashMap<Class<? extends AbstractJpaNode>, HashSet<String>> NON_UPDATE_ASPECT_NAME_SETS = new HashMap<Class<? extends AbstractJpaNode>, HashSet<String>>();

	protected void addNonUpdateAspectNamesTo(@SuppressWarnings("unused") Set<String> nonUpdateAspectNames) {
	// when you override this method, don't forget to include:
	//	super.addNonUpdateAspectNamesTo(nonUpdateAspectNames);
	}

	public void stateChanged() {
		this.fireStateChanged();
		if (this.parent != null) {
			this.parent.stateChanged();
		}
	}


	// ********** convenience stuff **********

	/**
	 * Useful for building validation messages.
	 */
	protected static final String[] EMPTY_STRING_ARRAY = StringTools.EMPTY_STRING_ARRAY;


	/**
	 * Adapter used to synchronize a context collection container with its corresponding
	 * resource container.
	 * @param <C> the type of context elements
	 * @param <R> the type of resource elements
	 */
	protected abstract class CollectionContainer<C, R>
		implements Iterable<C>
	{
		protected final Vector<C> contextElements = new Vector<C>();

		protected CollectionContainer() {
			super();
		}

		/**
		 * Return the container's current set of resource elements.
		 * These are what the context elements will be synchronized to.
		 */
		protected abstract Iterable<R> getResourceElements();

		/**
		 * Return the resource element corresponding to the specified context
		 * element.
		 */
		protected abstract R getResourceElement(C contextElement);

		/**
		 * Build and return a context element for the given resource element
		 */
		protected abstract C buildContextElement(R resourceElement);

		/**
		 * Return the property name for event notification when the collection is changed.
		 */
		protected abstract String getContextElementsPropertyName();

		/**
		 * clients needs to call initialize if necessary
		 */
		public void initialize() {
			for (R resourceElement : this.getResourceElements()) {
				this.contextElements.add(this.buildContextElement(resourceElement));
			}
		}

		/**
		 * Return an Iterable of the context elements
		 */
		public Iterable<C> getContextElements() {
			return new LiveCloneIterable<C>(this.contextElements);
		}

		public C get(int index) {
			return this.contextElements.get(index);
		}

		public Iterator<C> iterator() {
			return new CloneIterator<C>(this.contextElements);
		}

		/**
		 * Return the size of the context elements collection
		 */
		public int getContextElementsSize() {
			return this.contextElements.size();
		}

		/**
		 * Add a context element for the specified resource element at the
		 * specified index.
		 */
		public C addContextElement(int index, R resourceElement) {
			return this.addContextElement_(index, this.buildContextElement(resourceElement));
		}

		/**
		 * Add the specified context element to the container at the specified
		 * index.
		 */
		protected abstract C addContextElement_(int index, C element);

		/**
		 * Add context elements for the specified resource elements at the
		 * specified index.
		 */
		public Iterable<C> addContextElements(int index, Iterable<R> resourceElements) {
			ArrayList<C> newContextElements = new ArrayList<C>();
			for (R resourceElement : resourceElements) {
				newContextElements.add(this.buildContextElement(resourceElement));
			}
			return this.addAll(index, newContextElements);
		}

		/**
		 * Add the specified context elements to the collection.
		 */
		protected abstract Iterable<C> addAll(int index, Iterable<C> elements);

		/**
		 * Remove the specified context element from the container.
		 */
		public abstract void removeContextElement(C element);

		/**
		 * Remove the specified context elements from the container.
		 */
		public abstract void removeAll(Iterable<C> elements);

		protected abstract void moveContextElement(int index, C element);

		protected void disposeElement(C element) {
			//override if you need to dispose an element when it is removed
		}

		@Override
		public String toString() {
			return this.contextElements.toString();
		}
	}


	/**
	 * Adapter used to synchronize a context collection container with its corresponding
	 * resource container.
	 * @param <C> the type of context elements
	 * @param <R> the type of resource elements
	 */
	protected abstract class AbstractContextCollectionContainer<C extends JpaContextNode, R>
		extends CollectionContainer<C, R>
	{
		protected AbstractContextCollectionContainer() {
			super();
		}

		/**
		 * Using the specified adapter, synchronize a context container with its
		 * corresponding resource container: moving, removing, and adding elements
		 * as necessary.
		 * <p>
		 * We can do this because:<ul>
		 * <li>the XML translators will <em>move</em> the EMF elements when
		 * appropriate (as opposed to simply rebuilding them in place).
		 * <li>the Java resource model will re-use existing annotations when
		 * appropriate (as opposed to simply rebuilding them in place).
		 * </ul>
		 */
		public void synchronizeWithResourceModel() {
			sync(true);  // true = sync
		}

		/**
		 * @see #synchronizeWithResourceModel(Adapter)
		 */
		public void update() {
			sync(false);  // false = update
		}

		/**
		 * The specified <code>sync</code> flag controls whether any surviving
		 * context nodes are either <em>synchronized</em> (<code>true</code>) or
		 * <em>updated</em> (<code>false</code>).
		 */
		protected void sync(boolean sync) {
			HashSet<C> contextElements = CollectionTools.set(this.getContextElements());
			ArrayList<C> contextElementsToSync = new ArrayList<C>(contextElements.size());
			int resourceIndex = 0;

			for (R resourceElement : this.getResourceElements()) {
				boolean match = false;
				for (Iterator<C> stream = contextElements.iterator(); stream.hasNext(); ) {
					C contextElement = stream.next();
					if (Tools.valuesAreEqual(this.getResourceElement(contextElement), resourceElement)) {
						// we don't know the source index because the element has been moved by previously moved elements
						this.moveContextElement(resourceIndex, contextElement);
						stream.remove();
						// TODO perform update here someday...
						contextElementsToSync.add(contextElement);
						match = true;
						break;
					}
				}
				if ( ! match) {
					// added elements are sync'ed during construction or will be
					// updated during the next "update" (which is triggered by
					// their addition to the model)
					this.addContextElement(resourceIndex, resourceElement);
				}
				resourceIndex++;
			}
			// remove any leftover context elements
			for (C contextElement : contextElements) {
				removeContextElement(contextElement);
			}
			// TODO bjv
			// take care of the structural changes before sync'ing the remaining elements;
			// we might be able to do this inline once we get rid of the "list change" events
			// and go with only add, remove, etc. list events
			// (these syncs will trigger "list change" events with list aspect adapters, which
			// trigger refreshes of UI adapters (e.g. TableModelAdapter) which will prematurely
			// discover any structural changes... :( )
			// see ItemAspectListValueModelAdapter.itemAspectChanged(EventObject)
			for (C contextElement : contextElementsToSync) {
				if (sync) {
					contextElement.synchronizeWithResourceModel();
				} else {
					contextElement.update();
				}
			}
		}
	}


	/**
	 * Adapter used to synchronize a context collection container with its corresponding
	 * resource container.
	 * @param <C> the type of context elements
	 * @param <R> the type of resource elements
	 */
	protected abstract class ContextCollectionContainer<C extends JpaContextNode, R>
		extends AbstractContextCollectionContainer<C, R>
	{
		protected ContextCollectionContainer() {
			super();
		}

		@Override
		protected C addContextElement_(int index, C element) {
			// ignore the index - not a list
			AbstractJpaNode.this.addItemToCollection(element, this.contextElements, this.getContextElementsPropertyName());
			return element;
		}

		@Override
		protected Iterable<C> addAll(int index, Iterable<C> elements) {
			// ignore the index - not a list
			AbstractJpaNode.this.addItemsToCollection(elements, this.contextElements, this.getContextElementsPropertyName());
			return elements;
		}

		@Override
		public void removeContextElement(C contextElement) {
			AbstractJpaNode.this.removeItemFromCollection(contextElement, this.contextElements, this.getContextElementsPropertyName());
			this.disposeElement(contextElement);
		}

		@Override
		public void removeAll(Iterable<C> elements) {
			AbstractJpaNode.this.removeItemsFromCollection(elements, this.contextElements, this.getContextElementsPropertyName());
			for (C element : elements) {
				this.disposeElement(element);
			}
		}

		@Override
		protected void moveContextElement(int index, C element) {
			// NOP - not a list
		}
	}


	/**
	 * Adapter used to synchronize a context list container with its corresponding
	 * resource container.
	 * @param <C> the type of context elements
	 * @param <R> the type of resource elements
	 */
	protected abstract class ContextListContainer<C extends JpaContextNode, R>
		extends AbstractContextCollectionContainer<C, R>
	{
		protected ContextListContainer() {
			super();
		}

		@Override
		public ListIterable<C> getContextElements() {
			return new LiveCloneListIterable<C>(this.contextElements);
		}

		@Override
		protected abstract ListIterable<R> getResourceElements();

		/**
		 * Return the index of the specified context element.
		 */
		public int indexOfContextElement(C element) {
			return this.contextElements.indexOf(element);
		}

		public C getContextElement(int index) {
			return this.contextElements.elementAt(index);
		}

		@Override
		protected C addContextElement_(int index, C element) {
			AbstractJpaNode.this.addItemToList(index, element, this.contextElements, this.getContextElementsPropertyName());
			return element;
		}

		@Override
		public Iterable<C> addAll(int index, Iterable<C> elements) {
			AbstractJpaNode.this.addItemsToList(index, elements, this.contextElements, this.getContextElementsPropertyName());
			return elements;
		}

		/**
		 * Move the context element at the specified target index to the 
		 * specified source index.
		 */
		public void moveContextElement(int targetIndex, int sourceIndex) {
			AbstractJpaNode.this.moveItemInList(targetIndex, sourceIndex, this.contextElements, this.getContextElementsPropertyName());
		}

		@Override
		public void moveContextElement(int index, C element) {
			AbstractJpaNode.this.moveItemInList(index, element, this.contextElements, this.getContextElementsPropertyName());
		}

		/**
		 * clear the list of context elements
		 */
		public void clearContextList() {
			for (C element : this.contextElements) {
				this.disposeElement(element);
			}
			AbstractJpaNode.this.clearList(this.contextElements, getContextElementsPropertyName());
		}

		/**
		 * Remove the context element at the specified index from the container.
		 */
		public C removeContextElement(int index) {
			C element = AbstractJpaNode.this.removeItemFromList(index, this.contextElements, this.getContextElementsPropertyName());
			this.disposeElement(element);
			return element;
		}

		@Override
		public void removeContextElement(C element) {
			AbstractJpaNode.this.removeItemFromList(element, this.contextElements, this.getContextElementsPropertyName());
			this.disposeElement(element);
		}

		@Override
		public void removeAll(Iterable<C> elements) {
			AbstractJpaNode.this.removeItemsFromList(elements, this.contextElements, this.getContextElementsPropertyName());
			for (C element : elements) {
				this.disposeElement(element);
			}
		}
	}


	/**
	 * Adapter used to synchronize a context list container with its corresponding
	 * resource container.
	 * @param <C> the type of context elements
	 * @param <R> the type of resource elements
	 */
	protected abstract class ListContainer<C, R>
		extends CollectionContainer<C, R>
	{
		protected ListContainer() {
			super();
		}

		@Override
		public ListIterable<C> getContextElements() {
			return new LiveCloneListIterable<C>(this.contextElements);
		}

		@Override
		protected abstract ListIterable<R> getResourceElements();

		/**
		 * Return the index of the specified context element.
		 */
		public int indexOfContextElement(C element) {
			return this.contextElements.indexOf(element);
		}

		public C getContextElement(int index) {
			return this.contextElements.get(index);
		}

		@Override
		protected C addContextElement_(int index, C element) {
			AbstractJpaNode.this.addItemToList(index, element, this.contextElements, this.getContextElementsPropertyName());
			return element;
		}

		@Override
		protected Iterable<C> addAll(int index, Iterable<C> newContextElements) {
			AbstractJpaNode.this.addItemsToList(index, newContextElements, this.contextElements, this.getContextElementsPropertyName());
			return newContextElements;
		}

		/**
		 * Move the context element at the specified target index to the 
		 * specified source index.
		 */
		public void moveContextElement(int targetIndex, int sourceIndex) {
			AbstractJpaNode.this.moveItemInList(targetIndex, sourceIndex, this.contextElements, this.getContextElementsPropertyName());
		}

		@Override
		public void moveContextElement(int index, C element) {
			AbstractJpaNode.this.moveItemInList(index, element, this.contextElements, this.getContextElementsPropertyName());
		}

		@Override
		public void removeContextElement(C element) {
			AbstractJpaNode.this.removeItemFromList(element, this.contextElements, this.getContextElementsPropertyName());
			this.disposeElement(element);
		}

		/**
		 * Remove the context element at the specified index from the container.
		 */
		public C removeContextElement(int index) {
			C element = AbstractJpaNode.this.removeItemFromList(index, this.contextElements, this.getContextElementsPropertyName());
			this.disposeElement(element);
			return element;
		}

		@Override
		public void removeAll(Iterable<C> elements) {
			AbstractJpaNode.this.removeItemsFromList(elements, this.contextElements, this.getContextElementsPropertyName());
			for (C element : elements) {
				this.disposeElement(element);
			}
		}

		@Override
		protected void disposeElement(C element) {
			//override if you need to dispose an element when it is removed
		}

		public void synchronizeWithResourceModel() {
			ListIterable<R> resourceElements = getResourceElements();
			
			int index = 0;
			for (R resourceElement : resourceElements) {
				if (this.getContextElementsSize() > index) {
					if (this.getContextElement(index) != resourceElement) {
						this.addContextElement(index, resourceElement);
					}
				}
				else {
					this.addContextElement(index, resourceElement);			
				}
				index++;
			}
			
			for ( ; index < this.getContextElementsSize(); ) {
				this.removeContextElement(index);
			}
		}
	}
}
