/*******************************************************************************
 * Copyright (c) 2007, 2010 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.core.internal.resource.java.source;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jpt.core.resource.java.AnnotationContainer;
import org.eclipse.jpt.core.resource.java.NestableAnnotation;
import org.eclipse.jpt.utility.internal.CollectionTools;

/**
 * Utility methods for manipulating annotation containers.
 */
public final class AnnotationContainerTools {

	/**
	 * Add a nested annotation to the specified annotation container
	 * at the specified index.
	 * This method modifies both the resource model annotation container and the
	 * AST; with <em>no</em> change notification.
	 */
	public static <T extends NestableAnnotation> NestableAnnotation addNestedAnnotation(int index, AnnotationContainer<T> annotationContainer) {
		// add a new annotation to the end of the list...
		int sourceIndex = annotationContainer.getNestedAnnotationsSize();
		T nestedAnnotation = annotationContainer.addNestedAnnotation();
		nestedAnnotation.newAnnotation();
		// ...then move it to the specified index
		moveNestedAnnotation(index, sourceIndex, annotationContainer);
		return nestedAnnotation;
	}

	/**
	 * Move the nested annotation at the specified source index in the
	 * specified annotation container to the specified target index.
	 * This method modifies both the resource model annotation container and the
	 * AST; with <em>no</em> change notification.
	 */
	public static <T extends NestableAnnotation> void moveNestedAnnotation(int targetIndex, int sourceIndex, AnnotationContainer<T> annotationContainer) {
		if (targetIndex != sourceIndex) {
			moveNestedAnnotation_(targetIndex, sourceIndex, annotationContainer);
		}
	}

	private static <T extends NestableAnnotation> void moveNestedAnnotation_(int targetIndex, int sourceIndex, AnnotationContainer<T> annotationContainer) {
		NestableAnnotation nestedAnnotation = annotationContainer.moveNestedAnnotation(targetIndex, sourceIndex);
		syncAstAnnotationsAfterMove(targetIndex, sourceIndex, annotationContainer, nestedAnnotation);
	}

	/**
	 * An annotation was moved within the specified annotation container from
	 * the specified source index to the specified target index.
	 * Synchronize the AST annotations with the resource model annotation container,
	 * starting with the lower index to prevent overlap.
	 */
	private static <T extends NestableAnnotation> void syncAstAnnotationsAfterMove(int targetIndex, int sourceIndex, AnnotationContainer<T> annotationContainer, NestableAnnotation nestedAnnotation) {
		// move the Java annotation to the end of the list...
		nestedAnnotation.moveAnnotation(annotationContainer.getNestedAnnotationsSize());
		// ...then shift the other AST annotations over one slot...
		List<T> nestableAnnotations = CollectionTools.list(annotationContainer.getNestedAnnotations());
		if (sourceIndex < targetIndex) {
			for (int i = sourceIndex; i < targetIndex; i++) {
				nestableAnnotations.get(i).moveAnnotation(i);
			}
		} else {
			for (int i = sourceIndex; i > targetIndex; i-- ) {
				nestableAnnotations.get(i).moveAnnotation(i);
			}
		}
		// ...then move the AST annotation to the now empty slot at the target index
		nestedAnnotation.moveAnnotation(targetIndex);
	}

	/**
	 * Remove the nested annotation at the specified index in the
	 * specified annotation container.
	 * This method modifies both the resource model annotation container and the
	 * AST; with <em>no</em> change notification.
	 */
	public static <T extends NestableAnnotation> void removeNestedAnnotation(int index, AnnotationContainer<T> annotationContainer) {
		T nestedAnnotation = annotationContainer.removeNestedAnnotation(index);
		nestedAnnotation.removeAnnotation();
		syncAstAnnotationsAfterRemove(index, annotationContainer);
	}

	/**
	 * An annotation was removed from the specified annotation container at the
	 * specified index.
	 * Synchronize the AST annotations with the resource model annotation container,
	 * starting at the specified index to prevent overlap.
	 */
	private static <T extends NestableAnnotation> void syncAstAnnotationsAfterRemove(int index, AnnotationContainer<T> annotationContainer) {
		List<T> nestableAnnotations = CollectionTools.list(annotationContainer.getNestedAnnotations());
		for (int i = index; i < nestableAnnotations.size(); i++) {
			// the indices are the same because the model annotations are
			// already in the proper locations - it's the AST annotations that
			// need to be moved to the matching location
			nestableAnnotations.get(i).moveAnnotation(i);
		}
	}

	/**
	 * Initialize the specified resource model annotation container to be in
	 * sync with the specified AST. No change notification will occur.
	 */
	public static <T extends NestableAnnotation> void initialize(AnnotationContainer<T> annotationContainer, CompilationUnit astRoot) {
		// ignore the nested AST annotations themselves
		// (maybe someday we can use them during initialization...)
		int size = getNestedAstAnnotations(astRoot, annotationContainer).size();
		for (int i = 0; i < size; i++) {
			T nestedAnnotation = annotationContainer.addNestedAnnotation();
			nestedAnnotation.initialize(astRoot);
		}
	}

	/**
	 * Return a list of the nested AST annotations.
	 */
	private static <T extends NestableAnnotation> List<Annotation> getNestedAstAnnotations(CompilationUnit astRoot, AnnotationContainer<T> annotationContainer) {
		Annotation astContainerAnnotation = annotationContainer.getAstAnnotation(astRoot);
		if (astContainerAnnotation == null) {
			// seems unlikely the AST container annotation would be null,
			// since the resource container annotation is only created and
			// initialized (or synchronized) when the AST container annotation
			// is discovered
			return Collections.emptyList();
		}

		if (astContainerAnnotation.isMarkerAnnotation()) {
			return Collections.emptyList();  // no nested annotations
		}

		if (astContainerAnnotation.isSingleMemberAnnotation()) {
			return getNestedAstAnnotations((SingleMemberAnnotation) astContainerAnnotation, annotationContainer);
		}

		if (astContainerAnnotation.isNormalAnnotation()) {
			return getNestedAstAnnotations((NormalAnnotation) astContainerAnnotation, annotationContainer);
		}

		throw new IllegalStateException("unknown annotation type: " + astContainerAnnotation); //$NON-NLS-1$
	}

	private static <T extends NestableAnnotation> List<Annotation> getNestedAstAnnotations(SingleMemberAnnotation astContainerAnnotation, AnnotationContainer<T> annotationContainer) {
		return annotationContainer.getElementName().equals("value") ? //$NON-NLS-1$
				getAstAnnotations(astContainerAnnotation.getValue(), annotationContainer) :
				Collections.<Annotation>emptyList();
	}

	private static <T extends NestableAnnotation> List<Annotation> getNestedAstAnnotations(NormalAnnotation astContainerAnnotation, AnnotationContainer<T> annotationContainer) {
		MemberValuePair pair = getMemberValuePair(astContainerAnnotation, annotationContainer.getElementName());
		return (pair != null) ?
				getAstAnnotations(pair.getValue(), annotationContainer) :
				Collections.<Annotation>emptyList();
	}

	private static <T extends NestableAnnotation> List<Annotation> getAstAnnotations(Expression expression, AnnotationContainer<T> annotationContainer) {
		return (expression != null) ?
				getAstAnnotations_(expression, annotationContainer.getNestedAnnotationName()) :
				Collections.<Annotation>emptyList();
	}

	/**
	 * pre-condition: expression is not null
	 */
	private static <T extends NestableAnnotation> List<Annotation> getAstAnnotations_(Expression expression, String annotationName) {
		ArrayList<Annotation> result = new ArrayList<Annotation>();
		addAstAnnotationsTo(expression, annotationName, result);
		return result;
	}

	/**
	 * pre-condition: expression is not null
	 * <p>
	 * Add whatever annotations are represented by the specified expression to
	 * the specified list. Skip any non-annotation expressions.
	 */
	private static void addAstAnnotationsTo(Expression expression, String annotationName, ArrayList<Annotation> astAnnotations) {
		if (expression.getNodeType() == ASTNode.ARRAY_INITIALIZER) {
			addAstAnnotationsTo((ArrayInitializer) expression, annotationName, astAnnotations);
		} else {
			addAstAnnotationTo(expression, annotationName, astAnnotations);
		}
	}

	private static void addAstAnnotationsTo(ArrayInitializer arrayInitializer, String annotationName, ArrayList<Annotation> astAnnotations) {
		@SuppressWarnings("unchecked")
		List<Expression> expressions = arrayInitializer.expressions();
		for (Expression expression : expressions) {
			if (expression != null) {
				addAstAnnotationTo(expression, annotationName, astAnnotations);
			}
		}
	}

	private static void addAstAnnotationTo(Expression expression, String annotationName, ArrayList<Annotation> astAnnotations) {
		switch (expression.getNodeType()) {
			case ASTNode.NORMAL_ANNOTATION:
			case ASTNode.SINGLE_MEMBER_ANNOTATION:
			case ASTNode.MARKER_ANNOTATION:
				Annotation astAnnotation = (Annotation) expression;
				if (getQualifiedName(astAnnotation).equals(annotationName)) {
					astAnnotations.add(astAnnotation);
				}
				break;
			default:
				break;
		}
	}

	private static String getQualifiedName(Annotation astAnnotation) {
		ITypeBinding typeBinding = astAnnotation.resolveTypeBinding();
		if (typeBinding != null) {
			String resolvedName = typeBinding.getQualifiedName();
			if (resolvedName != null) {
				return resolvedName;
			}
		}
		return astAnnotation.getTypeName().getFullyQualifiedName();
	}

	private static MemberValuePair getMemberValuePair(NormalAnnotation annotation, String elementName) {
		@SuppressWarnings("unchecked")
		List<MemberValuePair> pairs = annotation.values();
		for (MemberValuePair pair : pairs) {
			if (pair.getName().getFullyQualifiedName().equals(elementName)) {
				return pair;
			}
		}
		return null;
	}

	/**
	 * Synchronize the resource model annotations in the specified annotation
	 * container with those in the specified AST. Trigger the appropriate change
	 * notification.
	 */
	public static <T extends NestableAnnotation> void synchronize(AnnotationContainer<T> annotationContainer, CompilationUnit astRoot) {
		List<Annotation> astAnnotations = getNestedAstAnnotations(astRoot, annotationContainer);
		Iterator<Annotation> astAnnotationStream = astAnnotations.iterator();

		for (T nestedAnnotation : annotationContainer.getNestedAnnotations()) {
			if (astAnnotationStream.hasNext()) {
				// matching AST annotation is present - synchronize the nested annotation
				astAnnotationStream.next();  // maybe someday we can pass this to the update
				nestedAnnotation.synchronizeWith(astRoot);
			} else {
				// no more AST annotations - remove the remaining nested annotations and exit
				annotationContainer.syncRemoveNestedAnnotations(astAnnotations.size());
				return;
			}
		}

		// add nested annotations for any remaining AST annotations
		while (astAnnotationStream.hasNext()) {
			annotationContainer.syncAddNestedAnnotation(astAnnotationStream.next());
		}
	}

	private AnnotationContainerTools() {
		super();
		throw new UnsupportedOperationException();
	}
}
