/*******************************************************************************
 * Copyright (c) 2010, 2011 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.jpa1.context.java;

import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jpt.common.core.resource.java.Annotation;
import org.eclipse.jpt.common.core.resource.java.JavaResourceMember;
import org.eclipse.jpt.common.core.resource.java.NestableAnnotation;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.common.utility.Filter;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.common.utility.internal.NotNullFilter;
import org.eclipse.jpt.common.utility.internal.iterables.CompositeListIterable;
import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
import org.eclipse.jpt.common.utility.internal.iterables.SubIterableWrapper;
import org.eclipse.jpt.common.utility.internal.iterables.TransformationIterable;
import org.eclipse.jpt.common.utility.internal.iterators.FilteringIterator;
import org.eclipse.jpt.jpa.core.context.Override_;
import org.eclipse.jpt.jpa.core.context.ReadOnlyBaseColumn;
import org.eclipse.jpt.jpa.core.context.ReadOnlyOverride;
import org.eclipse.jpt.jpa.core.context.TypeMapping;
import org.eclipse.jpt.jpa.core.context.VirtualOverride;
import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
import org.eclipse.jpt.jpa.core.context.java.JavaOverride;
import org.eclipse.jpt.jpa.core.context.java.JavaOverrideContainer;
import org.eclipse.jpt.jpa.core.context.java.JavaReadOnlyOverride;
import org.eclipse.jpt.jpa.core.context.java.JavaVirtualOverride;
import org.eclipse.jpt.jpa.core.internal.context.TableColumnTextRangeResolver;
import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools;
import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
import org.eclipse.jpt.jpa.core.internal.context.OverrideTextRangeResolver;
import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode;
import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOverrideContainer2_0;
import org.eclipse.jpt.jpa.core.resource.java.OverrideAnnotation;
import org.eclipse.jpt.jpa.db.Table;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;

/**
 * Java override container
 * <p>
 * <strong>NB:</strong> Although not typical, a Java override container can
 * correspond to only a subset of the annotations in the Java source code.
 * In that case, the index of a specified override must be translated to its
 * corresponding annotation's index before we manipulate the annotations.
 * <p>
 * As of JPA 2.0, the only place we need these translations is for the attribute
 * overrides for an embedded collection. If an embedded collection is a
 * {@link java.util.Map Map}, the attribute overrides can override the mappings
 * for either the map's keys or the map's values. The names of the overrides for
 * the map's keys are prefixed with <code>"key."</code> while the overrides
 * for the map's values are prefixed with <code>"value."</code>.
 * (Just a bit of hack, courtesy of the JPA spec committee.)
 */
public abstract class AbstractJavaOverrideContainer<
			O extends JavaOverrideContainer.Owner,
			R extends JavaReadOnlyOverride,
			S extends JavaOverride,
			V extends JavaVirtualOverride,
			A extends OverrideAnnotation & NestableAnnotation
		>
	extends AbstractJavaJpaContextNode
	implements JavaOverrideContainer2_0
{
	/**
	 * this can be <code>null</code> if the container is "read-only"
	 * (i.e. a <em>null</em> container)
	 * @see #getOwner2_0()
	 */
	protected final O owner;

	protected final Vector<S> specifiedOverrides = new Vector<S>();
	protected final SpecifiedOverrideContainerAdapter specifiedOverrideContainerAdapter = new SpecifiedOverrideContainerAdapter();

	protected final Vector<V> virtualOverrides = new Vector<V>();
	protected final VirtualOverrideContainerAdapter virtualOverrideContainerAdapter = new VirtualOverrideContainerAdapter();


	protected AbstractJavaOverrideContainer(JavaJpaContextNode parent, O owner) {
		super(parent);
		this.owner = owner;
	}


	// ********** synchronize/update **********

	@Override
	public void synchronizeWithResourceModel() {
		super.synchronizeWithResourceModel();
		this.synchronizeNodesWithResourceModel(this.getSpecifiedOverrides());
		// the virtual overrides do not need a sync
	}

	@Override
	public void update() {
		super.update();
		this.updateSpecifiedOverrides();
		this.updateVirtualOverrides();
	}


	// ********** overrides **********

	@SuppressWarnings("unchecked")
	public ListIterable<R> getOverrides() {
		return new CompositeListIterable<R>(this.getReadOnlySpecifiedOverrides(), this.getReadOnlyVirtualOverrides());
	}

	public int getOverridesSize() {
		return this.specifiedOverrides.size() + this.virtualOverrides.size();
	}

	public R getOverrideNamed(String name) {
		return this.selectOverrideNamed(this.getOverrides(), name);
	}

	public Iterable<String> getOverrideNames() {
		return new FilteringIterable<String>(this.getOverrideNames_(), NotNullFilter.<String>instance());
	}

	protected Iterable<String> getOverrideNames_() {
		return new TransformationIterable<R, String>(this.getOverrides()) {
			@Override
			protected String transform(R override) {
				return override.getName();
			}
		};
	}


	// ********** override conversions **********

	/**
	 * <em>Silently</em> add the new virtual override before removing the
	 * specified override, or the <em>update</em> will discover the missing
	 * virtual override and add it preemptively.
	 */
	public V convertOverrideToVirtual(Override_ override) {
		if (override.isVirtual()) {
			throw new IllegalArgumentException("Override is already virtual: " + override); //$NON-NLS-1$
		}

		@SuppressWarnings("unchecked")
		S specifiedOverride = (S) override;
		int virtualIndex = this.virtualOverrides.size();
		String overrideName = specifiedOverride.getName();
		V virtualOverride = null;
		// make sure the specified override actually overrides something before building the virtual override
		if (this.overrideWillBeVirtual(overrideName, specifiedOverride)) {
			virtualOverride = this.buildVirtualOverride(overrideName);
			this.virtualOverrides.add(virtualIndex, virtualOverride);
		}

		this.removeSpecifiedOverride(specifiedOverride);  // trigger update

		if (virtualOverride != null) {
			this.fireItemAdded(VIRTUAL_OVERRIDES_LIST, virtualIndex, virtualOverride);
		}
		return virtualOverride;
	}

	/**
	 * Return whether the specified override name will be a
	 * <em>virtual</em> override when the specified specified override is
	 * removed from the container. The override name must be among the
	 * valid override names and it must not correspond to any of the
	 * remaining specified overrides.
	 */
	protected boolean overrideWillBeVirtual(String overrideName, S specifiedOverrideToBeRemoved) {
		return CollectionTools.contains(this.getAllOverridableNames(), overrideName) &&
				(this.getSpecifiedOverrideNamed(overrideName, specifiedOverrideToBeRemoved) == null);
	}

	/**
	 * <em>Silently</em> remove the virtual override and add the new specified
	 * override before naming the specified override, or the <em>update</em>
	 * will discover the dangling virtual override and remove it preemptively.
	 */
	public S convertOverrideToSpecified(VirtualOverride override) {
		if ( ! override.isVirtual()) {
			throw new IllegalArgumentException("Override is already specified: " + override); //$NON-NLS-1$
		}

		@SuppressWarnings("unchecked")
		V virtualOverride = (V) override;
		int virtualIndex = this.virtualOverrides.indexOf(virtualOverride);
		this.virtualOverrides.remove(virtualIndex);

		int specifiedIndex = this.specifiedOverrides.size();
		S specifiedOverride = this.buildSpecifiedOverride(this.buildOverrideAnnotation(specifiedIndex));
		this.specifiedOverrides.add(specifiedIndex, specifiedOverride);

		this.initializeSpecifiedOverride(specifiedOverride, virtualOverride);  // trigger update

		this.fireItemRemoved(VIRTUAL_OVERRIDES_LIST, virtualIndex, virtualOverride);
		this.fireItemAdded(SPECIFIED_OVERRIDES_LIST, specifiedIndex, specifiedOverride);		
		return specifiedOverride;
	}

	protected abstract void initializeSpecifiedOverride(S specifiedOverride, V virtualOverride);


	// ********** specified overrides **********

	public ListIterable<S> getSpecifiedOverrides() {
		return new LiveCloneListIterable<S>(this.specifiedOverrides);
	}

	@SuppressWarnings("unchecked")
	protected ListIterable<R> getReadOnlySpecifiedOverrides() {
		// S should always be a subtype of R, but we can't enforce that in the
		// class declaration...
		return (ListIterable<R>) this.getSpecifiedOverrides();
	}

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

	public S getSpecifiedOverride(int index) {
		return this.specifiedOverrides.get(index);
	}

	public S getSpecifiedOverrideNamed(String name) {
		return this.getSpecifiedOverrideNamed(name, null);
	}

	@SuppressWarnings("unchecked")
	protected S getSpecifiedOverrideNamed(String name, S exclude) {
		return (S) this.selectOverrideNamed(this.getReadOnlySpecifiedOverrides(), name, exclude);
	}

	protected S addSpecifiedOverride() {
		return this.addSpecifiedOverride(this.specifiedOverrides.size());
	}

	protected S addSpecifiedOverride(int index) {
		A annotation = this.buildOverrideAnnotation(index);
		return this.addSpecifiedOverride_(index, annotation);
	}

	@SuppressWarnings("unchecked")
	protected A buildOverrideAnnotation(int index) {
		int annotationIndex = this.calculateNewAnnotationIndex(index);
		return (A) this.getResourceMember().addAnnotation(annotationIndex, this.getOverrideAnnotationName());
	}

	protected int calculateNewAnnotationIndex(int index) {
		// if we are adding to the end of the specified list,
		// put the annotation after all the existing annotations
		if (index == this.specifiedOverrides.size()) {
			return CollectionTools.size(this.getOverrideAnnotations());
		}

		// if we are adding to the front of the specified list,
		// put the annotation before of all the existing annotations
		if (index == 0) {
			return 0;
		}

		// if we are adding to the middle of the specified list,
		// put the annotation immediately after all the previous override's
		// existing annotation
		return this.translateToAnnotationIndex(index - 1) + 1;
	}

	/**
	 * pre-condition: override exists at the specified index
	 */
	protected int translateToAnnotationIndex(int index) {
		return CollectionTools.indexOf(this.getOverrideAnnotations(), this.specifiedOverrides.get(index).getOverrideAnnotation());
	}

	protected abstract String getOverrideAnnotationName();

	protected void removeSpecifiedOverride(S override) {
		this.removeSpecifiedOverride(this.specifiedOverrides.indexOf(override));
	}

	protected void removeSpecifiedOverride(int index) {
		this.removeOverrideAnnotation(index);
		this.removeSpecifiedOverride_(index);
	}

	protected void removeOverrideAnnotation(int index) {
		int annotationIndex = this.translateToAnnotationIndex(index);
		this.getResourceMember().removeAnnotation(annotationIndex, this.getOverrideAnnotationName());
	}

	protected void removeSpecifiedOverride_(int index) {
		this.removeItemFromList(index, this.specifiedOverrides, SPECIFIED_OVERRIDES_LIST);
	}

	public void moveSpecifiedOverride(int targetIndex, int sourceIndex) {
		this.moveOverrideAnnotation(targetIndex, sourceIndex);
		this.moveItemInList(targetIndex, sourceIndex, this.specifiedOverrides, SPECIFIED_OVERRIDES_LIST);
	}

	protected void moveOverrideAnnotation(int targetIndex, int sourceIndex) {
		int targetAnnotationIndex = this.translateToAnnotationIndex(targetIndex);
		int sourceAnnotationIndex = this.translateToAnnotationIndex(sourceIndex);
		this.getResourceMember().moveAnnotation(targetAnnotationIndex, sourceAnnotationIndex, this.getOverrideAnnotationName());
	}

	protected abstract S buildSpecifiedOverride(A overrideAnnotation);

	protected void updateSpecifiedOverrides() {
		ContextContainerTools.update(this.specifiedOverrideContainerAdapter);
	}

	protected Iterable<A> getRelevantOverrideAnnotations() {
		return new FilteringIterable<A>(this.getOverrideAnnotations()) {
			@Override
			protected boolean accept(A annotation) {
				String overrideName = annotation.getName();
				return (overrideName != null) && this.getOwner().isRelevant(overrideName);
			}
			protected JavaOverrideContainer2_0.Owner getOwner() {
				return AbstractJavaOverrideContainer.this.getOwner2_0();
			}
		};
	}

	protected Iterable<A> getOverrideAnnotations() {
		return new SubIterableWrapper<NestableAnnotation, A>((this.overrideAnnotations()));
	}

	protected Iterable<NestableAnnotation> overrideAnnotations() {
		return (this.owner == null) ? EmptyIterable.<NestableAnnotation>instance() : this.overrideAnnotations_();
	}

	/**
	 * pre-condition: {@link #owner} is not <code>null</code>
	 */
	protected Iterable<NestableAnnotation> overrideAnnotations_() {
		return this.getResourceMember().getAnnotations(this.getOverrideAnnotationName());
	}

	protected void moveSpecifiedOverride_(int index, S override) {
		this.moveItemInList(index, override, this.specifiedOverrides, SPECIFIED_OVERRIDES_LIST);
	}

	protected S addSpecifiedOverride_(int index, A overrideAnnotation) {
		S override = this.buildSpecifiedOverride(overrideAnnotation);
		this.addItemToList(index, override, this.specifiedOverrides, SPECIFIED_OVERRIDES_LIST);
		return override;
	}

	protected void removeSpecifiedOverride_(S override) {
		this.removeSpecifiedOverride_(this.specifiedOverrides.indexOf(override));
	}

	/**
	 * specified override container adapter
	 */
	protected class SpecifiedOverrideContainerAdapter
		implements ContextContainerTools.Adapter<S, A>
	{
		public Iterable<S> getContextElements() {
			return AbstractJavaOverrideContainer.this.getSpecifiedOverrides();
		}
		public Iterable<A> getResourceElements() {
			return AbstractJavaOverrideContainer.this.getRelevantOverrideAnnotations();
		}
		@SuppressWarnings("unchecked")
		public A getResourceElement(S contextElement) {
			return (A) contextElement.getOverrideAnnotation();
		}
		public void moveContextElement(int index, S element) {
			AbstractJavaOverrideContainer.this.moveSpecifiedOverride_(index, element);
		}
		public void addContextElement(int index, A resourceElement) {
			AbstractJavaOverrideContainer.this.addSpecifiedOverride_(index, resourceElement);
		}
		public void removeContextElement(S element) {
			AbstractJavaOverrideContainer.this.removeSpecifiedOverride_(element);
		}
	}


	// ********** virtual overrides **********

	public ListIterable<V> getVirtualOverrides() {
		return new LiveCloneListIterable<V>(this.virtualOverrides);
	}

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

	@SuppressWarnings("unchecked")
	protected ListIterable<R> getReadOnlyVirtualOverrides() {
		// V should always be a subtype of R, but we can't enforce that in the
		// class declaration...
		return (ListIterable<R>) this.getVirtualOverrides();
	}

	protected void updateVirtualOverrides() {
		ContextContainerTools.update(this.virtualOverrideContainerAdapter);
	}

	/**
	 * Return the overridable names that are not already in the list of
	 * specified overrides.
	 */
	protected Iterable<String> getVirtualOverrideNames() {
		return CollectionTools.iterable(this.virtualOverrideNames());
	}

	protected Iterator<String> virtualOverrideNames() {
		return new FilteringIterator<String>(this.getAllOverridableNames()) {
			@Override
			protected boolean accept(String name) {
				return AbstractJavaOverrideContainer.this.overrideIsVirtual(name);
			}
		};
	}

	protected boolean overrideIsVirtual(String name) {
		return this.getSpecifiedOverrideNamed(name) == null;
	}

	protected void moveVirtualOverride(int index, V override) {
		this.moveItemInList(index, override, this.virtualOverrides, VIRTUAL_OVERRIDES_LIST);
	}

	protected V addVirtualOverride(int index, String name) {
		V override = this.buildVirtualOverride(name);
		this.addItemToList(index, override, this.virtualOverrides, VIRTUAL_OVERRIDES_LIST);
		return override;
	}

	protected abstract V buildVirtualOverride(String name);

	protected void removeVirtualOverride(V override) {
		this.removeItemFromList(override, this.virtualOverrides, VIRTUAL_OVERRIDES_LIST);
	}

	/**
	 * virtual override container adapter
	 * NB: the context override is matched with a resource override by name
	 */
	protected class VirtualOverrideContainerAdapter
		implements ContextContainerTools.Adapter<V, String>
	{
		public Iterable<V> getContextElements() {
			return AbstractJavaOverrideContainer.this.getVirtualOverrides();
		}
		public Iterable<String> getResourceElements() {
			return AbstractJavaOverrideContainer.this.getVirtualOverrideNames();
		}
		public String getResourceElement(V contextElement) {
			return contextElement.getName();
		}
		public void moveContextElement(int index, V element) {
			AbstractJavaOverrideContainer.this.moveVirtualOverride(index, element);
		}
		public void addContextElement(int index, String resourceElement) {
			AbstractJavaOverrideContainer.this.addVirtualOverride(index, resourceElement);
		}
		public void removeContextElement(V element) {
			AbstractJavaOverrideContainer.this.removeVirtualOverride(element);
		}
	}


	// ********** misc **********

	protected JavaOverrideContainer2_0.Owner getOwner2_0() {
		return (JavaOverrideContainer2_0.Owner) this.owner;
	}

	public TypeMapping getTypeMapping() {
		return this.owner.getTypeMapping();
	}

	protected JavaResourceMember getResourceMember() {
		return this.owner.getResourceMember();
	}

	public TypeMapping getOverridableTypeMapping() {
		return this.owner.getOverridableTypeMapping();
	}

	public Iterable<String> getAllOverridableNames() {
		return (this.owner != null) ? this.owner.getAllOverridableNames() : EmptyIterable.<String>instance();
	}

	public boolean tableNameIsInvalid(String tableName) {
		return this.owner.tableNameIsInvalid(tableName);
	}

	public Iterable<String> getCandidateTableNames() {
		return this.owner.getCandidateTableNames();
	}

	public Table resolveDbTable(String tableName) {
		return this.owner.resolveDbTable(tableName);
	}

	public String getDefaultTableName() {
		return this.owner.getDefaultTableName();
	}

	public JptValidator buildOverrideValidator(ReadOnlyOverride override, OverrideTextRangeResolver textRangeResolver) {
		return this.owner.buildOverrideValidator(override, this, textRangeResolver);
	}

	public JptValidator buildColumnValidator(ReadOnlyOverride override, ReadOnlyBaseColumn column, ReadOnlyBaseColumn.Owner columnOwner, TableColumnTextRangeResolver textRangeResolver) {
		return this.owner.buildColumnValidator(override, column, columnOwner, textRangeResolver);
	}

	public String getPossiblePrefix() {
		return this.getOwner2_0().getPossiblePrefix();
	}

	public String getWritePrefix() {
		return this.getOwner2_0().getWritePrefix();
	}

	protected R selectOverrideNamed(Iterable<R> overrides, String name) {
		return this.selectOverrideNamed(overrides, name, null);
	}

	protected R selectOverrideNamed(Iterable<R> overrides, String name, S exclude) {
		for (R override : overrides) {
			if (override == exclude) {
				continue;  // skip
			}
			if (this.valuesAreEqual(override.getName(), name)) {
				return override;
			}
		}
		return null;
	}


	// ********** code completion **********

	@Override
	public Iterable<String> getJavaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) {
		Iterable<String> result = super.getJavaCompletionProposals(pos, filter, astRoot);
		if (result != null) {
			return result;
		}
		for (R override : this.getOverrides()) {
			result = override.getJavaCompletionProposals(pos, filter, astRoot);
			if (result != null) {
				return result;
			}
		}
		return null;
	}


	// ********** validation **********

	@Override
	public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
		super.validate(messages, reporter, astRoot);
		for (R override: this.getOverrides()) {
			override.validate(messages, reporter, astRoot);
		}
	}

	public TextRange getValidationTextRange(CompilationUnit astRoot) {
		TextRange textRange = this.getValidationAnnotationTextRange(astRoot);
		return (textRange != null) ? textRange : this.owner.getValidationTextRange(astRoot);
	}

	protected TextRange getValidationAnnotationTextRange(CompilationUnit astRoot) {
		Annotation annotation = this.getValidationAnnotation();
		return (annotation == null) ? null : annotation.getTextRange(astRoot);
	}

	protected Annotation getValidationAnnotation() {
		JavaResourceMember resourceMember = this.getResourceMember();
		return resourceMember.getAnnotation(this.getOverrideAnnotationName());
	}
}
