/*******************************************************************************
 * 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.BaseColumnTextRangeResolver;
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, BaseColumnTextRangeResolver 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());
	}
}
