/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.codeassist.complete;

import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.lookup.*;

/**
 * Node representing a Javadoc comment including code selection.
 */
public class CompletionJavadoc extends Javadoc {

	Expression completionNode;

	public CompletionJavadoc(int sourceStart, int sourceEnd) {
		super(sourceStart, sourceEnd);
	}

	/**
	 * @return Returns the completionNode.
	 */
	public Expression getCompletionNode() {
		return this.completionNode;
	}

	/**
	 * Resolve selected node if not null and throw exception to let clients know
	 * that it has been found.
	 * 
	 * @throws CompletionNodeFound
	 */
	private void internalResolve(Scope scope) {
		if (this.completionNode != null) {
			if (this.completionNode instanceof CompletionOnJavadocTag) {
				((CompletionOnJavadocTag)this.completionNode).filterPossibleTags(scope);
			} else {
				boolean resolve = true;
				if (this.completionNode instanceof CompletionOnJavadocParamNameReference) {
					resolve = ((CompletionOnJavadocParamNameReference)this.completionNode).token != null;
				} else if (this.completionNode instanceof CompletionOnJavadocTypeParamReference) {
					resolve = ((CompletionOnJavadocTypeParamReference)this.completionNode).token != null;
				}
				if (resolve) {
					switch (scope.kind) {
						case Scope.CLASS_SCOPE:
							this.completionNode.resolveType((ClassScope)scope);
							break;
						case Scope.METHOD_SCOPE:
							this.completionNode.resolveType((MethodScope) scope);
							break;
					}
				}
				if (this.completionNode instanceof CompletionOnJavadocParamNameReference) {
					CompletionOnJavadocParamNameReference paramNameReference = (CompletionOnJavadocParamNameReference) this.completionNode;
					if (scope.kind == Scope.METHOD_SCOPE) {
						paramNameReference.missingParams = missingParamTags(paramNameReference.binding, (MethodScope)scope);
					}
					if (paramNameReference.token == null || paramNameReference.token.length == 0) {
						paramNameReference.missingTypeParams = missingTypeParameterTags(paramNameReference.binding, scope);
					}
				} else if (this.completionNode instanceof CompletionOnJavadocTypeParamReference) {
					CompletionOnJavadocTypeParamReference typeParamReference = (CompletionOnJavadocTypeParamReference) this.completionNode;
					typeParamReference.missingParams = missingTypeParameterTags(typeParamReference.resolvedType, scope);
				}
			}
			Binding qualifiedBinding = null;
			if (this.completionNode instanceof CompletionOnJavadocQualifiedTypeReference) {
				CompletionOnJavadocQualifiedTypeReference typeRef = (CompletionOnJavadocQualifiedTypeReference) this.completionNode;
				if (typeRef.packageBinding == null) {
					qualifiedBinding = typeRef.resolvedType;
				} else {
					qualifiedBinding = typeRef.packageBinding;
				}
			} else if (this.completionNode instanceof CompletionOnJavadocMessageSend) {
				CompletionOnJavadocMessageSend msg = (CompletionOnJavadocMessageSend) this.completionNode;
				if (!msg.receiver.isThis()) qualifiedBinding = msg.receiver.resolvedType;
			} else if (this.completionNode instanceof CompletionOnJavadocAllocationExpression) {
				CompletionOnJavadocAllocationExpression alloc = (CompletionOnJavadocAllocationExpression) this.completionNode;
				qualifiedBinding = alloc.type.resolvedType;
			}
			throw new CompletionNodeFound(this.completionNode, qualifiedBinding, scope);
		}
	}
	
	/*
	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#print(int, java.lang.StringBuffer)
	 */
	public StringBuffer print(int indent, StringBuffer output) {
		printIndent(indent, output).append("/**\n"); //$NON-NLS-1$
		boolean nodePrinted = false;
		if (this.paramReferences != null) {
			for (int i = 0, length = this.paramReferences.length; i < length; i++) {
				printIndent(indent, output).append(" * @param "); //$NON-NLS-1$		
				this.paramReferences[i].print(indent, output).append('\n');
				if (!nodePrinted && this.completionNode != null) {
					nodePrinted =  this.completionNode == this.paramReferences[i];
				}
			}
		}
		if (this.paramTypeParameters != null) {
			for (int i = 0, length = this.paramTypeParameters.length; i < length; i++) {
				printIndent(indent, output).append(" * @param <"); //$NON-NLS-1$		
				this.paramTypeParameters[i].print(indent, output).append(">\n"); //$NON-NLS-1$
				if (!nodePrinted && this.completionNode != null) {
					nodePrinted =  this.completionNode == this.paramTypeParameters[i];
				}
			}
		}
		if (this.returnStatement != null) {
			printIndent(indent, output).append(" * @"); //$NON-NLS-1$
			this.returnStatement.print(indent, output).append('\n');
		}
		if (this.exceptionReferences != null) {
			for (int i = 0, length = this.exceptionReferences.length; i < length; i++) {
				printIndent(indent, output).append(" * @throws "); //$NON-NLS-1$		
				this.exceptionReferences[i].print(indent, output).append('\n');
				if (!nodePrinted && this.completionNode != null) {
					nodePrinted =  this.completionNode == this.exceptionReferences[i];
				}
			}
		}
		if (this.seeReferences != null) {
			for (int i = 0, length = this.seeReferences.length; i < length; i++) {
				printIndent(indent, output).append(" * @see "); //$NON-NLS-1$		
				this.seeReferences[i].print(indent, output).append('\n');
				if (!nodePrinted && this.completionNode != null) {
					nodePrinted =  this.completionNode == this.seeReferences[i];
				}
			}
		}
		if (!nodePrinted && this.completionNode != null) {
			printIndent(indent, output).append(" * "); //$NON-NLS-1$		
			this.completionNode.print(indent, output).append('\n');
		}
		printIndent(indent, output).append(" */\n"); //$NON-NLS-1$
		return output;
	}

	/**
	 * Resolve completion node if not null and throw exception to let clients know
	 * that it has been found.
	 * 
	 * @throws CompletionNodeFound
	 */
	public void resolve(ClassScope scope) {
		super.resolve(scope);
		internalResolve(scope);
	}

	/**
	 * Resolve completion node if not null and throw exception to let clients know
	 * that it has been found.
	 * 
	 * @throws CompletionNodeFound
	 */
	public void resolve(CompilationUnitScope scope) {
		internalResolve(scope);
	}

	/**
	 * Resolve completion node if not null and throw exception to let clients know
	 * that it has been found.
	 * 
	 * @throws CompletionNodeFound
	 */
	public void resolve(MethodScope scope) {
		super.resolve(scope);
		internalResolve(scope);
	}

	/*
	 * Look for missing method @param tags
	 */
	private char[][] missingParamTags(Binding paramNameRefBinding, MethodScope methScope) {

		// Verify if there's some possible param tag
		AbstractMethodDeclaration md = methScope.referenceMethod();
		int paramTagsSize = this.paramReferences == null ? 0 : this.paramReferences.length;
		if (md == null) return null;
		int argumentsSize = md.arguments == null ? 0 : md.arguments.length;
		if (argumentsSize == 0) return null;
		
		// Store all method arguments if there's no @param in javadoc
		if (paramTagsSize == 0) {
			char[][] missingParams = new char[argumentsSize][];
			for (int i = 0; i < argumentsSize; i++) {
				missingParams[i] = md.arguments[i].name;
			}
			return missingParams;
		}

		// Look for missing arguments
		char[][] missingParams = new char[argumentsSize][];
		int size = 0;
		for (int i = 0; i < argumentsSize; i++) {
			Argument arg = md.arguments[i];
			boolean found = false;
			int paramNameRefCount = 0;
			for (int j = 0; j < paramTagsSize && !found; j++) {
				JavadocSingleNameReference param = this.paramReferences[j];
				if (arg.binding == param.binding) {
					if (param.binding == paramNameRefBinding) { // do not count first occurence of param name reference
						paramNameRefCount++;
						found = paramNameRefCount > 1;
					} else {
						found = true;
					}
				}
			}
			if (!found) {
				missingParams[size++] = arg.name;
			}
		}
		if (size > 0) {
			if (size != argumentsSize) {
				System.arraycopy(missingParams, 0, missingParams = new char[size][], 0, size);
			}
			return missingParams;
		}
		return null;
	}

	/*
	 * Look for missing type parameters @param tags
	 */
	private char[][] missingTypeParameterTags(Binding paramNameRefBinding, Scope scope) {
		int paramTypeParamLength = this.paramTypeParameters == null ? 0 : this.paramTypeParameters.length;

		// Verify if there's any type parameter to tag
		TypeParameter[] parameters =  null;
		TypeVariableBinding[] typeVariables = null;
		switch (scope.kind) {
			case Scope.METHOD_SCOPE:
				AbstractMethodDeclaration methodDeclaration = ((MethodScope)scope).referenceMethod();
				if (methodDeclaration == null) return null;
				parameters = methodDeclaration.typeParameters();
				typeVariables = methodDeclaration.binding.typeVariables;
				break;
			case Scope.CLASS_SCOPE:
				TypeDeclaration typeDeclaration = ((ClassScope) scope).referenceContext;
				parameters = typeDeclaration.typeParameters;
				typeVariables = typeDeclaration.binding.typeVariables;
				break;
		}
		if (typeVariables == null || typeVariables.length == 0) return null;
		
		// Store all type parameters if there's no @param in javadoc
		if (parameters != null) {
			int typeParametersLength = parameters.length;
			if (paramTypeParamLength == 0) {
				char[][] missingParams = new char[typeParametersLength][];
				for (int i = 0; i < typeParametersLength; i++) {
					missingParams[i] = parameters[i].name;
				}
				return missingParams;
			}

			// Look for missing type parameter
			char[][] missingParams = new char[typeParametersLength][];
			int size = 0;
			for (int i = 0; i < typeParametersLength; i++) {
				TypeParameter parameter = parameters[i];
				boolean found = false;
				int paramNameRefCount = 0;
				for (int j = 0; j < paramTypeParamLength && !found; j++) {
					if (parameter.binding == this.paramTypeParameters[j].resolvedType) {
						if (parameter.binding == paramNameRefBinding) { // do not count first occurence of param nmae reference
							paramNameRefCount++;
							found = paramNameRefCount > 1;
						} else {
							found = true;
						}
					}
				}
				if (!found) {
					missingParams[size++] = parameter.name;
				}
			}
			if (size > 0) {
				if (size != typeParametersLength) {
					System.arraycopy(missingParams, 0, missingParams = new char[size][], 0, size);
				}
				return missingParams;
			}
		}
		return null;
	}
}
