/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.jdt.internal.corext.util;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.Assert;

import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;


/**
 * Finds overriding and overridden methods based on the Java model.
 */
// @see JDTUIHelperClasses
public class MethodOverrideTester {
	private static class Substitutions {

		public static final Substitutions EMPTY_SUBST= new Substitutions();

		private HashMap<String, String[]> fMap;

		public Substitutions() {
			fMap= null;
		}

		public void addSubstitution(String typeVariable, String substitution, String erasure) {
			if (fMap == null) {
				fMap= new HashMap<>(3);
			}
			fMap.put(typeVariable, new String[] { substitution, erasure });
		}

		private String[] getSubstArray(String typeVariable) {
			if (fMap != null) {
				return fMap.get(typeVariable);
			}
			return null;
		}

		public String getSubstitution(String typeVariable) {
			String[] subst= getSubstArray(typeVariable);
			if (subst != null) {
				return subst[0];
			}
			return null;
		}

		public String getErasure(String typeVariable) {
			String[] subst= getSubstArray(typeVariable);
			if (subst != null) {
				return subst[1];
			}
			return null;
		}
	}

	private final IType fFocusType;
	private final ITypeHierarchy fHierarchy;

	private Map <IMethod, Substitutions> fMethodSubstitutions;
	private Map<IType, Substitutions> fTypeVariableSubstitutions;

	public MethodOverrideTester(IType focusType, ITypeHierarchy hierarchy) {
		if (focusType == null || hierarchy == null) {
			throw new IllegalArgumentException();
		}
		fFocusType= focusType;
		fHierarchy= hierarchy;
		fTypeVariableSubstitutions= null;
		fMethodSubstitutions= null;
	}

	public IType getFocusType() {
		return fFocusType;
	}

	public ITypeHierarchy getTypeHierarchy() {
		return fHierarchy;
	}

	/**
	 * Finds the method that declares the given method. A declaring method is the 'original' method declaration that does
	 * not override nor implement a method. <code>null</code> is returned it the given method does not override
	 * a method. When searching, super class are examined before implemented interfaces.
	 * @param overriding the overriding method
	 * @param testVisibility If true the result is tested on visibility. Null is returned if the method is not visible.
	 * @return the declaring method, or <code>null</code>
	 * @throws JavaModelException if a problem occurs
	 */
	public IMethod findDeclaringMethod(IMethod overriding, boolean testVisibility) throws JavaModelException {
		IMethod result= null;
		IMethod overridden= findOverriddenMethod(overriding, testVisibility);
		while (overridden != null) {
			result= overridden;
			overridden= findOverriddenMethod(result, testVisibility);
		}
		return result;
	}

	/**
	 * Finds the method that is overridden by the given method.
	 * First the super class is examined and then the implemented interfaces.
	 * @param overriding the overriding method
	 * @param testVisibility If true the result is tested on visibility. Null is returned if the method is not visible.
	 * @return a method that is directly overridden by the given method, or <code>null</code>
	 * @throws JavaModelException if a problem occurs
	 */
	public IMethod findOverriddenMethod(IMethod overriding, boolean testVisibility) throws JavaModelException {
		int flags= overriding.getFlags();
		if (Flags.isPrivate(flags) || Flags.isStatic(flags) || overriding.isConstructor()) {
			return null;
		}

		IType type= overriding.getDeclaringType();
		IType superClass= fHierarchy.getSuperclass(type);
		if (superClass != null) {
			IMethod res= findOverriddenMethodInHierarchy(superClass, overriding);
			if (res != null) {
				if (!testVisibility || JavaModelUtil.isVisibleInHierarchy(res, type.getPackageFragment())) {
					return res;
				}
			}
		}
		IType[] interfaces= fHierarchy.getSuperInterfaces(type);
		for (int i= 0; i < interfaces.length; i++) {
			IMethod res= findOverriddenMethodInHierarchy(interfaces[i], overriding);
			if (res != null) {
				return res; // methods from interfaces are always public and therefore visible
			}
		}
		return null;
	}

	/**
	 * Finds the directly overridden method in a type and its super types. First the super class is examined and then the implemented interfaces.
	 * With generics it is possible that 2 methods in the same type are overidden at the same time. In that case, the first overridden method found is returned.
	 * 	@param type The type to find methods in
	 * @param overriding The overriding method
	 * @return The first overridden method or <code>null</code> if no method is overridden
	 * @throws JavaModelException if a problem occurs
	 */
	public IMethod findOverriddenMethodInHierarchy(IType type, IMethod overriding) throws JavaModelException {
		IMethod method= findOverriddenMethodInType(type, overriding);
		if (method != null) {
			return method;
		}
		IType superClass= fHierarchy.getSuperclass(type);
		if (superClass != null) {
			IMethod res=  findOverriddenMethodInHierarchy(superClass, overriding);
			if (res != null) {
				return res;
			}
		}
		IType[] superInterfaces= fHierarchy.getSuperInterfaces(type);
		for (int i= 0; i < superInterfaces.length; i++) {
			IMethod res= findOverriddenMethodInHierarchy(superInterfaces[i], overriding);
			if (res != null) {
				return res;
			}
		}
		return method;
	}

	/**
	 * Finds an overridden method in a type. With generics it is possible that 2 methods in the same type are overridden at the same time.
	 * In that case the first overridden method found is returned.
	 * @param overriddenType The type to find methods in
	 * @param overriding The overriding method
	 * @return The first overridden method or <code>null</code> if no method is overridden
	 * @throws JavaModelException if a problem occurs
	 */
	public IMethod findOverriddenMethodInType(IType overriddenType, IMethod overriding) throws JavaModelException {
		int flags= overriding.getFlags();
		if (Flags.isPrivate(flags) || Flags.isStatic(flags) || overriding.isConstructor())
			return null;
		IMethod[] overriddenMethods= overriddenType.getMethods();
		for (int i= 0; i < overriddenMethods.length; i++) {
			IMethod overridden= overriddenMethods[i];
			flags= overridden.getFlags();
			if (Flags.isPrivate(flags) || Flags.isStatic(flags) || overridden.isConstructor())
				continue;
			if (isSubsignature(overriding, overridden)) {
				return overridden;
			}
		}
		return null;
	}

	/**
	 * Finds an overriding method in a type.
	 * @param overridingType The type to find methods in
	 * @param overridden The overridden method
	 * @return The overriding method or <code>null</code> if no method is overriding.
	 * @throws JavaModelException if a problem occurs
	 */
	public IMethod findOverridingMethodInType(IType overridingType, IMethod overridden) throws JavaModelException {
		int flags= overridden.getFlags();
		if (Flags.isPrivate(flags) || Flags.isStatic(flags) || overridden.isConstructor())
			return null;
		IMethod[] overridingMethods= overridingType.getMethods();
		for (int i= 0; i < overridingMethods.length; i++) {
			IMethod overriding= overridingMethods[i];
			flags= overriding.getFlags();
			if (Flags.isPrivate(flags) || Flags.isStatic(flags) || overriding.isConstructor())
				continue;
			if (isSubsignature(overriding, overridden)) {
				return overriding;
			}
		}
		return null;
	}

	/**
	 * Tests if a method is a subsignature of another method.
	 * @param overriding overriding method (m1)
	 * @param overridden overridden method (m2)
	 * @return <code>true</code> iff the method <code>m1</code> is a subsignature of the method <code>m2</code>.
	 * 		This is one of the requirements for m1 to override m2.
	 * 		Accessibility and return types are not taken into account.
	 * 		Note that subsignature is <em>not</em> symmetric!
	 * @throws JavaModelException if a problem occurs
	 */
	public boolean isSubsignature(IMethod overriding, IMethod overridden) throws JavaModelException {
		if (!overridden.getElementName().equals(overriding.getElementName())) {
			return false;
		}
		int nParameters= overridden.getNumberOfParameters();
		if (nParameters != overriding.getNumberOfParameters()) {
			return false;
		}

		if (!hasCompatibleTypeParameters(overriding, overridden)) {
			return false;
		}

		return nParameters == 0 || hasCompatibleParameterTypes(overriding, overridden);
	}

	private boolean hasCompatibleTypeParameters(IMethod overriding, IMethod overridden) throws JavaModelException {
		ITypeParameter[] overriddenTypeParameters= overridden.getTypeParameters();
		ITypeParameter[] overridingTypeParameters= overriding.getTypeParameters();
		int nOverridingTypeParameters= overridingTypeParameters.length;
		if (overriddenTypeParameters.length != nOverridingTypeParameters) {
			return nOverridingTypeParameters == 0;
		}
		Substitutions overriddenSubst= getMethodSubstitions(overridden);
		Substitutions overridingSubst= getMethodSubstitions(overriding);
		for (int i= 0; i < nOverridingTypeParameters; i++) {
			String erasure1= overriddenSubst.getErasure(overriddenTypeParameters[i].getElementName());
			String erasure2= overridingSubst.getErasure(overridingTypeParameters[i].getElementName());
			if (erasure1 == null || !erasure1.equals(erasure2)) {
				return false;
			}
			// comparing only the erasure is not really correct: Need to compare all bounds, that can be in different order
			int nBounds= overriddenTypeParameters[i].getBounds().length;
			if (nBounds > 1 && nBounds != overridingTypeParameters[i].getBounds().length) {
				return false;
			}
		}
		return true;
	}

	private boolean hasCompatibleParameterTypes(IMethod overriding, IMethod overridden) throws JavaModelException {
		String[] overriddenParamTypes= overridden.getParameterTypes();
		String[] overridingParamTypes= overriding.getParameterTypes();

		String[] substitutedOverriding= new String[overridingParamTypes.length];
		boolean testErasure= false;

		for (int i= 0; i < overridingParamTypes.length; i++) {
			String overriddenParamSig= overriddenParamTypes[i];
			String overriddenParamName= getSubstitutedTypeName(overriddenParamSig, overridden);
			String overridingParamName= getSubstitutedTypeName(overridingParamTypes[i], overriding);
			substitutedOverriding[i]= overridingParamName;
			if (!overriddenParamName.equals(overridingParamName)) {
				testErasure= true;
				break;
			}
		}
		if (testErasure) {
			for (int i= 0; i < overridingParamTypes.length; i++) {
				String overriddenParamSig= overriddenParamTypes[i];
				String overriddenParamName= getErasedTypeName(overriddenParamSig, overridden);
				String overridingParamName= substitutedOverriding[i];
				if (overridingParamName == null)
					overridingParamName= getSubstitutedTypeName(overridingParamTypes[i], overriding);
				if (!overriddenParamName.equals(overridingParamName)) {
					return false;
				}
			}
		}
		return true;
	}

	private String getVariableSubstitution(IMember context, String variableName) throws JavaModelException {
		IType type;
		if (context instanceof IMethod) {
			String subst= getMethodSubstitions((IMethod) context).getSubstitution(variableName);
			if (subst != null) {
				return subst;
			}
			type= context.getDeclaringType();
		} else {
			type= (IType) context;
		}
		String subst= getTypeSubstitions(type).getSubstitution(variableName);
		if (subst != null) {
			return subst;
		}
		IJavaElement parent= type.getParent();
		if (parent instanceof IMethod) {
			return getVariableSubstitution((IMethod) parent, variableName);
		} else if (type.getDeclaringType() != null) {
			return getVariableSubstitution(type.getDeclaringType(), variableName);
		}
		return variableName; // not a type variable
	}

	private String getVariableErasure(IMember context, String variableName) throws JavaModelException {
		IType type;
		if (context instanceof IMethod) {
			String subst= getMethodSubstitions((IMethod) context).getErasure(variableName);
			if (subst != null) {
				return subst;
			}
			type= context.getDeclaringType();
		} else {
			type= (IType) context;
		}
		String subst= getTypeSubstitions(type).getErasure(variableName);
		if (subst != null) {
			return subst;
		}
		IJavaElement parent= type.getParent();
		if (parent instanceof IMethod) {
			return getVariableErasure((IMethod) parent, variableName);
		} else if (type.getDeclaringType() != null) {
			return getVariableErasure(type.getDeclaringType(), variableName);
		}
		return variableName; // not a type variable
	}

	/*
	 * Returns the substitutions for a method's type parameters
	 */
	private Substitutions getMethodSubstitions(IMethod method) throws JavaModelException {
		if (fMethodSubstitutions == null) {
			fMethodSubstitutions= new LRUMap<>(3);
		}

		Substitutions s= fMethodSubstitutions.get(method);
		if (s == null) {
			ITypeParameter[] typeParameters= method.getTypeParameters();
			if (typeParameters.length == 0) {
				s= Substitutions.EMPTY_SUBST;
			} else {
				IType instantiatedType= method.getDeclaringType();
				s= new Substitutions();
				for (int i= 0; i < typeParameters.length; i++) {
					ITypeParameter curr= typeParameters[i];
					s.addSubstitution(curr.getElementName(), '+' + String.valueOf(i), getTypeParameterErasure(curr, instantiatedType));
				}
			}
			fMethodSubstitutions.put(method, s);
		}
		return s;
	}

	/*
	 * Returns the substitutions for a type's type parameters
	 */
	private Substitutions getTypeSubstitions(IType type) throws JavaModelException {
		if (fTypeVariableSubstitutions == null) {
			fTypeVariableSubstitutions= new HashMap<>();
			computeSubstitutions(fFocusType, null, null);
		}
		Substitutions subst= fTypeVariableSubstitutions.get(type);
		if (subst == null) {
			return Substitutions.EMPTY_SUBST;
		}
		return subst;
	}

	private void computeSubstitutions(IType instantiatedType, IType instantiatingType, String[] typeArguments) throws JavaModelException {
		Substitutions s= new Substitutions();
		fTypeVariableSubstitutions.put(instantiatedType, s);

		ITypeParameter[] typeParameters= instantiatedType.getTypeParameters();

		if (instantiatingType == null) { // the focus type
			for (int i= 0; i < typeParameters.length; i++) {
				ITypeParameter curr= typeParameters[i];
				// use star to make type variables different from type refs
				s.addSubstitution(curr.getElementName(), '*' + curr.getElementName(), getTypeParameterErasure(curr, instantiatedType));
			}
		} else {
			if (typeParameters.length == typeArguments.length) {
				for (int i= 0; i < typeParameters.length; i++) {
					ITypeParameter curr= typeParameters[i];
					String substString= getSubstitutedTypeName(typeArguments[i], instantiatingType); // substitute in the context of the instantiatingType
					String erasure= getErasedTypeName(typeArguments[i], instantiatingType); // get the erasure from the type argument
					s.addSubstitution(curr.getElementName(), substString, erasure);
				}
			} else if (typeArguments.length == 0) { // raw type reference
				for (int i= 0; i < typeParameters.length; i++) {
					ITypeParameter curr= typeParameters[i];
					String erasure= getTypeParameterErasure(curr, instantiatedType);
					s.addSubstitution(curr.getElementName(), erasure, erasure);
				}
			} else {
				// code with errors
			}
		}
		String superclassTypeSignature= instantiatedType.getSuperclassTypeSignature();
		if (superclassTypeSignature != null) {
			String[] superTypeArguments= Signature.getTypeArguments(superclassTypeSignature);
			IType superclass= fHierarchy.getSuperclass(instantiatedType);
			if (superclass != null && !fTypeVariableSubstitutions.containsKey(superclass)) {
				computeSubstitutions(superclass, instantiatedType, superTypeArguments);
			}
		}
		String[] superInterfacesTypeSignature;
		if (instantiatedType.isAnonymous()) {
			// special case: superinterface is also returned by IType#getSuperclassTypeSignature()
			superInterfacesTypeSignature= new String[] { superclassTypeSignature };
		} else {
			superInterfacesTypeSignature= instantiatedType.getSuperInterfaceTypeSignatures();
		}
		int nInterfaces= superInterfacesTypeSignature.length;
		if (nInterfaces > 0) {
			IType[] superInterfaces= fHierarchy.getSuperInterfaces(instantiatedType);
			if (superInterfaces.length == nInterfaces) {
				for (int i= 0; i < nInterfaces; i++) {
					String[] superTypeArguments= Signature.getTypeArguments(superInterfacesTypeSignature[i]);
					IType superInterface= superInterfaces[i];
					if (!fTypeVariableSubstitutions.containsKey(superInterface)) {
						computeSubstitutions(superInterface, instantiatedType, superTypeArguments);
					}
				}
			}
		}
	}

	private String getTypeParameterErasure(ITypeParameter typeParameter, IType context) throws JavaModelException {
		String[] bounds= typeParameter.getBounds();
		if (bounds.length > 0) {
			return getErasedTypeName(Signature.createTypeSignature(bounds[0], false), context);
		}
		return "Object"; //$NON-NLS-1$
	}


	/**
	 * Translates the type signature to a 'normalized' type name where all variables are substituted for the given type or method context.
	 * The returned name contains only simple names and can be used to compare against other substituted type names
	 * @param typeSig The type signature to translate
	 * @param context The context for the substitution
	 * @return a type name
	 * @throws JavaModelException if a problem occurs
	 */
	private String getSubstitutedTypeName(String typeSig, IMember context) throws JavaModelException {
		return internalGetSubstitutedTypeName(typeSig, context, false, new StringBuffer()).toString();
	}

	private String getErasedTypeName(String typeSig, IMember context) throws JavaModelException {
		return internalGetSubstitutedTypeName(typeSig, context, true, new StringBuffer()).toString();
	}

	private StringBuffer internalGetSubstitutedTypeName(String typeSig, IMember context, boolean erasure, StringBuffer buf) throws JavaModelException {
		int sigKind= Signature.getTypeSignatureKind(typeSig);
		switch (sigKind) {
			case Signature.BASE_TYPE_SIGNATURE:
				return buf.append(Signature.toString(typeSig));
			case Signature.ARRAY_TYPE_SIGNATURE:
				internalGetSubstitutedTypeName(Signature.getElementType(typeSig), context, erasure, buf);
				for (int i= Signature.getArrayCount(typeSig); i > 0; i--) {
					buf.append('[').append(']');
				}
				return buf;
			case Signature.CLASS_TYPE_SIGNATURE: {
				String erasureSig= Signature.getTypeErasure(typeSig);
				String erasureName= Signature.getSimpleName(Signature.toString(erasureSig));

				char ch= erasureSig.charAt(0);
				if (ch == Signature.C_RESOLVED) {
					buf.append(erasureName);
				} else if (ch == Signature.C_UNRESOLVED) { // could be a type variable
					if (erasure) {
						buf.append(getVariableErasure(context, erasureName));
					} else {
						buf.append(getVariableSubstitution(context, erasureName));
					}
				} else {
					Assert.isTrue(false, "Unknown class type signature"); //$NON-NLS-1$
				}
				if (!erasure) {
					String[] typeArguments= Signature.getTypeArguments(typeSig);
					if (typeArguments.length > 0) {
						buf.append('<');
						for (int i= 0; i < typeArguments.length; i++) {
							if (i > 0) {
								buf.append(',');
							}
							internalGetSubstitutedTypeName(typeArguments[i], context, erasure, buf);
						}
						buf.append('>');
					}
				}
				return buf;
			}
			case Signature.TYPE_VARIABLE_SIGNATURE:
				String varName= Signature.toString(typeSig);
				if (erasure) {
					return buf.append(getVariableErasure(context, varName));
				} else {
					return buf.append(getVariableSubstitution(context, varName));
				}
			case Signature.WILDCARD_TYPE_SIGNATURE: {
				buf.append('?');
				char ch= typeSig.charAt(0);
				if (ch == Signature.C_STAR) {
					return buf;
				} else if (ch == Signature.C_EXTENDS) {
					buf.append(" extends "); //$NON-NLS-1$
				} else {
					buf.append(" super "); //$NON-NLS-1$
				}
				return internalGetSubstitutedTypeName(typeSig.substring(1), context, erasure, buf);
			}
			case Signature.CAPTURE_TYPE_SIGNATURE:
				return internalGetSubstitutedTypeName(typeSig.substring(1), context, erasure, buf);
			default:
				Assert.isTrue(false, "Unhandled type signature kind"); //$NON-NLS-1$
				return buf;
		}
	}

}
