/*******************************************************************************
 * Copyright (c) 2005, 2007 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.compiler.apt.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ElementVisitor;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.apt.dispatch.BaseProcessingEnvImpl;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationHolder;
import org.eclipse.jdt.internal.compiler.lookup.BinaryLocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodVerifier;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;

public class ExecutableElementImpl extends ElementImpl implements
		ExecutableElement {
	
	private Name _name = null;
	
	/* package */ ExecutableElementImpl(BaseProcessingEnvImpl env, MethodBinding binding) {
		super(env, binding);
	}

	@Override
	public <R, P> R accept(ElementVisitor<R, P> v, P p)
	{
		return v.visitExecutable(this, p);
	}

	@Override
	protected AnnotationBinding[] getAnnotationBindings()
	{
		return ((MethodBinding)_binding).getAnnotations();
	}

	@Override
	public AnnotationValue getDefaultValue() {
		MethodBinding binding = (MethodBinding)_binding;
		Object defaultValue = binding.getDefaultValue();
		if (defaultValue != null) return new AnnotationValueImpl(_env, defaultValue, binding.returnType);
		return null;
	}
	
	@Override
	public List<? extends Element> getEnclosedElements() {
		return Collections.emptyList();
	}

	@Override
	public Element getEnclosingElement() {
		MethodBinding binding = (MethodBinding)_binding;
		if (null == binding.declaringClass) {
			return null;
		}
		return _env.getFactory().newElement(binding.declaringClass);
	}

	@Override
	public String getFileName() {
		ReferenceBinding dc = ((MethodBinding)_binding).declaringClass;
		char[] name = dc.getFileName();
		if (name == null)
			return null;
		return new String(name);
	}

	@Override
	public ElementKind getKind() {
		MethodBinding binding = (MethodBinding)_binding;
		if (binding.isConstructor()) {
			return ElementKind.CONSTRUCTOR;
		}
		else if (CharOperation.equals(binding.selector, TypeConstants.CLINIT)) {
			return ElementKind.STATIC_INIT;
		}
		else if (CharOperation.equals(binding.selector, TypeConstants.INIT)) {
			return ElementKind.INSTANCE_INIT;
		}
		else {
			return ElementKind.METHOD;
		}
	}

	@Override
	public Set<Modifier> getModifiers() {
		MethodBinding binding = (MethodBinding)_binding;
		return Factory.getModifiers(binding.modifiers, getKind());
	}

	@Override
	PackageElement getPackage()
	{
		MethodBinding binding = (MethodBinding)_binding;
		if (null == binding.declaringClass) {
			return null;
		}
		return _env.getFactory().newPackageElement(binding.declaringClass.fPackage);
	}

	@Override
	public List<? extends VariableElement> getParameters() {
		MethodBinding binding = (MethodBinding)_binding;
		int length = binding.parameters == null ? 0 : binding.parameters.length;
		if (0 != length) {
			AbstractMethodDeclaration methodDeclaration = binding.sourceMethod();
			List<VariableElement> params = new ArrayList<VariableElement>(length);
			if (methodDeclaration != null) {
				for (Argument argument : methodDeclaration.arguments) {
					VariableElement param = new VariableElementImpl(_env, argument.binding);
					params.add(param);
				}
			} else {
				// binary method
				boolean isEnumConstructor = binding.isConstructor()
						&& binding.declaringClass.isEnum()
						&& binding.declaringClass.isBinaryBinding()
						&& ((binding.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0);
				AnnotationBinding[][] parameterAnnotationBindings = null;
				AnnotationHolder annotationHolder = binding.declaringClass.retrieveAnnotationHolder(binding, false);
				if (annotationHolder != null) {
					parameterAnnotationBindings = annotationHolder.getParameterAnnotations();
				}
				// we need to filter the synthetic arguments
				if (isEnumConstructor) {
					if (length == 2) {
						// the two arguments are only the two synthetic arguments
						return Collections.emptyList();
					}
					for (int i = 2; i < length; i++) {
						TypeBinding typeBinding = binding.parameters[i];
						StringBuilder builder = new StringBuilder("arg");//$NON-NLS-1$
						builder.append(i - 2);
						VariableElement param = new VariableElementImpl(_env,
								new BinaryLocalVariableBinding(
										String.valueOf(builder).toCharArray(),
										typeBinding,
										0,
										null));
						params.add(param);
					}
				} else {
					int i = 0;
					for (TypeBinding typeBinding : binding.parameters) {
						StringBuilder builder = new StringBuilder("arg");//$NON-NLS-1$
						builder.append(i);
						VariableElement param = new VariableElementImpl(_env,
								new BinaryLocalVariableBinding(
										String.valueOf(builder).toCharArray(),
										typeBinding,
										0,
										parameterAnnotationBindings != null ? parameterAnnotationBindings[i] : null));
						params.add(param);
						i++;
					}
				}
			}
			return Collections.unmodifiableList(params);
		}
		return Collections.emptyList();
	}

	@Override
	public TypeMirror getReturnType() {
		MethodBinding binding = (MethodBinding)_binding;
		if (binding.returnType == null) {
			return null;
		}
		else return _env.getFactory().newTypeMirror(binding.returnType);
	}

	@Override
	public Name getSimpleName() {
		MethodBinding binding = (MethodBinding)_binding;
		if (_name == null) {
			_name = new NameImpl(binding.selector);
		}
		return _name;
	}
	
	@Override
	public List<? extends TypeMirror> getThrownTypes() {
		MethodBinding binding = (MethodBinding)_binding;
		if (binding.thrownExceptions.length == 0) {
			return Collections.emptyList();
		}
		List<TypeMirror> list = new ArrayList<TypeMirror>(binding.thrownExceptions.length);
		for (ReferenceBinding exception : binding.thrownExceptions) {
			list.add(_env.getFactory().newTypeMirror(exception));
		}
		return list;
	}

	@Override
	public List<? extends TypeParameterElement> getTypeParameters() {
		MethodBinding binding = (MethodBinding)_binding;
		TypeVariableBinding[] variables = binding.typeVariables();
		if (variables.length == 0) {
			return Collections.emptyList();
		}
		List<TypeParameterElement> params = new ArrayList<TypeParameterElement>(variables.length); 
		for (TypeVariableBinding variable : variables) {
			params.add(_env.getFactory().newTypeParameterElement(variable, this));
		}
		return Collections.unmodifiableList(params);
	}

	@Override
	public boolean hides(Element hidden)
	{
		if (!(hidden instanceof ExecutableElementImpl)) {
			return false;
		}
		MethodBinding hiderBinding = (MethodBinding)_binding;
		MethodBinding hiddenBinding = (MethodBinding)((ExecutableElementImpl)hidden)._binding;
		if (hiderBinding == hiddenBinding) {
			return false;
		}
		if (hiddenBinding.isPrivate()) {
			return false;
		}
		// See JLS 8.4.8: hiding only applies to static methods
		if (!hiderBinding.isStatic() || !hiddenBinding.isStatic()) {
			return false;
		}
		// check names
		if (!CharOperation.equals(hiddenBinding.selector, hiderBinding.selector)) {
			return false;
		}
		// check parameters
		if (!_env.getLookupEnvironment().methodVerifier().doesMethodOverride(hiderBinding, hiddenBinding)) {
			return false;
		}
		return null != hiderBinding.declaringClass.findSuperTypeWithSameErasure(hiddenBinding.declaringClass); 
	}

	@Override
	public boolean isVarArgs() {
		return ((MethodBinding) _binding).isVarargs();
	}

	/**
	 * Return true if this method overrides {@code overridden} in the context of {@code type}.  For
	 * instance, consider 
	 * <pre>
	 *   interface A { void f(); }
	 *   class B { void f() {} }
	 *   class C extends B implements I { }
	 * </pre> 
	 * In the context of B, B.f() does not override A.f(); they are unrelated.  But in the context of
	 * C, B.f() does override A.f().  That is, the copy of B.f() that C inherits overrides A.f().
	 * This is equivalent to considering two questions: first, does C inherit B.f(); if so, does
	 * the inherited C.f() override A.f().  If B.f() were private, for instance, then in the context
	 * of C it would still not override A.f().  
	 * 
	 * @see javax.lang.model.util.Elements#overrides(ExecutableElement, ExecutableElement, TypeElement)
     * @jls3 8.4.8 Inheritance, Overriding, and Hiding
     * @jls3 9.4.1 Inheritance and Overriding
	 */
	public boolean overrides(ExecutableElement overridden, TypeElement type)
	{
		MethodBinding overriddenBinding = (MethodBinding)((ExecutableElementImpl) overridden)._binding;
		ReferenceBinding overriderContext = (ReferenceBinding)((TypeElementImpl)type)._binding;
		if ((MethodBinding)_binding == overriddenBinding)
			return false;
		if (overriddenBinding.isPrivate()) {
			return false;
		}
		char[] selector = ((MethodBinding)_binding).selector;
		if (!CharOperation.equals(selector, overriddenBinding.selector))
			return false;
		
		// Construct a binding to the equivalent of this (the overrider) as it would be inherited by 'type'.
		// Can only do this if 'type' is descended from the overrider.
		// Second clause of the AND is required to match a peculiar javac behavior.
		if (null == overriderContext.findSuperTypeWithSameErasure(((MethodBinding)_binding).declaringClass) &&
				null == ((MethodBinding)_binding).declaringClass.findSuperTypeWithSameErasure(overriderContext)) {
			return false;
		}
		MethodBinding overriderBinding = new MethodBinding((MethodBinding)_binding, overriderContext);
		if (overriderBinding.isPrivate()) {
			// a private method can never override another method.  The other method would either be
			// private itself, in which case it would not be visible; or this would be a restriction 
			// of access, which is a compile-time error.
			return false;
		}
		
		TypeBinding match = overriderBinding.declaringClass.findSuperTypeWithSameErasure(overriddenBinding.declaringClass);
		if (!(match instanceof ReferenceBinding)) return false;

		org.eclipse.jdt.internal.compiler.lookup.MethodBinding[] superMethods = ((ReferenceBinding)match).getMethods(selector);
		for (int i = 0, length = superMethods.length; i < length; i++) {
			if (superMethods[i].original() == overriddenBinding) {
				LookupEnvironment lookupEnvironment = _env.getLookupEnvironment();
				if (lookupEnvironment == null) return false;
				MethodVerifier methodVerifier = lookupEnvironment.methodVerifier();
				org.eclipse.jdt.internal.compiler.lookup.MethodBinding superMethod = superMethods[i];
				return !superMethod.isPrivate()
					&& !(superMethod.isDefault() && (superMethod.declaringClass.getPackage()) != overriderBinding.declaringClass.getPackage())
					&& methodVerifier.doesMethodOverride(overriderBinding, superMethod);
			}
		}
		return false;
	}

}
