/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.psi.infos;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.JavaVersionService;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.RecursionGuard;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
import com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.containers.ConcurrentWeakHashMap;
import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Map;

/**
 * @author ik, dsl
 */
public class MethodCandidateInfo extends CandidateInfo{
  public static final RecursionGuard ourOverloadGuard = RecursionManager.createGuard("overload.guard");
  public static final ThreadLocal<Map<PsiElement,  CurrentCandidateProperties>> CURRENT_CANDIDATE = new ThreadLocal<Map<PsiElement, CurrentCandidateProperties>>();
  @ApplicabilityLevelConstant private int myApplicabilityLevel; // benign race
  @ApplicabilityLevelConstant private int myPertinentApplicabilityLevel;
  private final PsiElement myArgumentList;
  private final PsiType[] myArgumentTypes;
  private final PsiType[] myTypeArguments;
  private PsiSubstitutor myCalcedSubstitutor; // benign race
  private final LanguageLevel myLanguageLevel;

  public MethodCandidateInfo(@NotNull PsiElement candidate,
                             PsiSubstitutor substitutor,
                             boolean accessProblem,
                             boolean staticsProblem,
                             PsiElement argumentList,
                             PsiElement currFileContext,
                             @Nullable PsiType[] argumentTypes,
                             PsiType[] typeArguments) {
    this(candidate, substitutor, accessProblem, staticsProblem, argumentList, currFileContext, argumentTypes, typeArguments,
         PsiUtil.getLanguageLevel(argumentList));
  }

  public MethodCandidateInfo(@NotNull PsiElement candidate,
                             @NotNull PsiSubstitutor substitutor,
                             boolean accessProblem,
                             boolean staticsProblem,
                             PsiElement argumentList,
                             PsiElement currFileContext,
                             @Nullable PsiType[] argumentTypes,
                             PsiType[] typeArguments,
                             @NotNull LanguageLevel languageLevel) {
    super(candidate, substitutor, accessProblem, staticsProblem, currFileContext);
    myArgumentList = argumentList;
    myArgumentTypes = argumentTypes;
    myTypeArguments = typeArguments;
    myLanguageLevel = languageLevel;
  }

  public boolean isVarargs() {
    return false;
  }

  public boolean isApplicable(){
    return getApplicabilityLevel() != ApplicabilityLevel.NOT_APPLICABLE;
  }

  @ApplicabilityLevelConstant
  private int getApplicabilityLevelInner() {
    final PsiType[] argumentTypes = getArgumentTypes();

    if (argumentTypes == null) return ApplicabilityLevel.NOT_APPLICABLE;

    int level = PsiUtil.getApplicabilityLevel(getElement(), getSubstitutor(), argumentTypes, myLanguageLevel);
    if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable()) level = ApplicabilityLevel.NOT_APPLICABLE;
    return level;
  }


  @ApplicabilityLevelConstant
  public int getApplicabilityLevel() {
    if(myApplicabilityLevel == 0){
      myApplicabilityLevel = getApplicabilityLevelInner();
    }
    return myApplicabilityLevel;
  }

  @ApplicabilityLevelConstant
  public int getPertinentApplicabilityLevel() {
    if (myPertinentApplicabilityLevel == 0) {
      myPertinentApplicabilityLevel = getPertinentApplicabilityLevelInner();
    }
    return myPertinentApplicabilityLevel;
  }
  
  public int getPertinentApplicabilityLevelInner() {
    if (myArgumentList == null || !PsiUtil.isLanguageLevel8OrHigher(myArgumentList)) {
      return getApplicabilityLevel();
    }
    @ApplicabilityLevelConstant int level;
    Integer boxedLevel = ourOverloadGuard.doPreventingRecursion(myArgumentList, false, new Computable<Integer>() {
      @Override
      public Integer compute() {
        if (PsiUtil.isLanguageLevel8OrHigher(myArgumentList)) {
          PsiSubstitutor substitutor = getSubstitutor(false);
          Map<PsiElement, CurrentCandidateProperties> map = CURRENT_CANDIDATE.get();
          if (map == null) {
            map = new ConcurrentWeakHashMap<PsiElement, CurrentCandidateProperties>();
            CURRENT_CANDIDATE.set(map);
          }
          final PsiMethod method = getElement();
          final CurrentCandidateProperties properties = new CurrentCandidateProperties(method, substitutor, isVarargs(), true);
          final CurrentCandidateProperties alreadyThere = map.put(getMarkerList(), properties);
          try {
            PsiType[] argumentTypes = getArgumentTypes();
            if (argumentTypes == null) {
              return ApplicabilityLevel.NOT_APPLICABLE;
            }

            final int applicabilityLevel = PsiUtil.getApplicabilityLevel(method, substitutor, argumentTypes, myLanguageLevel);
            if (!isVarargs() && applicabilityLevel < ApplicabilityLevel.FIXED_ARITY) {
              return ApplicabilityLevel.NOT_APPLICABLE;
            }
            return applicabilityLevel;
          }
          finally {
            if (alreadyThere == null) {
              map.remove(getMarkerList());
            } else {
              map.put(getMarkerList(), alreadyThere);
            }
          }
        }
        return getApplicabilityLevelInner();
      }

    });
    if (boxedLevel == null) {
      return getApplicabilityLevel();
    }
    level = boxedLevel;
    if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable(false)) level = ApplicabilityLevel.NOT_APPLICABLE;
    return level;
  }

  @NotNull
  public PsiSubstitutor getSiteSubstitutor() {
    PsiSubstitutor incompleteSubstitutor = super.getSubstitutor();
    if (myTypeArguments != null) {
      PsiMethod method = getElement();
      PsiTypeParameter[] typeParams = method.getTypeParameters();
      for (int i = 0; i < myTypeArguments.length && i < typeParams.length; i++) {
        incompleteSubstitutor = incompleteSubstitutor.put(typeParams[i], myTypeArguments[i]);
      }
    }
    return incompleteSubstitutor;
  }
  
  @NotNull
  @Override
  public PsiSubstitutor getSubstitutor() {
    return getSubstitutor(true);
  }

  @NotNull
  public PsiSubstitutor getSubstitutor(boolean includeReturnConstraint) {
    PsiSubstitutor substitutor = myCalcedSubstitutor;
    if (substitutor == null || !includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8) || isOverloadCheck()) {
      PsiSubstitutor incompleteSubstitutor = super.getSubstitutor();
      PsiMethod method = getElement();
      if (myTypeArguments == null) {
        final RecursionGuard.StackStamp stackStamp = PsiDiamondType.ourDiamondGuard.markStack();

        final PsiSubstitutor inferredSubstitutor = inferTypeArguments(DefaultParameterTypeInferencePolicy.INSTANCE, includeReturnConstraint);

         if (!stackStamp.mayCacheNow() ||
             isOverloadCheck() ||
             !includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8) ||
             getMarkerList() != null && PsiResolveHelper.ourGraphGuard.currentStack().contains(getMarkerList().getParent())) {
          return inferredSubstitutor;
        }

        myCalcedSubstitutor = substitutor = inferredSubstitutor;
      }
      else {
        PsiTypeParameter[] typeParams = method.getTypeParameters();
        for (int i = 0; i < myTypeArguments.length && i < typeParams.length; i++) {
          incompleteSubstitutor = incompleteSubstitutor.put(typeParams[i], myTypeArguments[i]);
        }
        myCalcedSubstitutor = substitutor = incompleteSubstitutor;
      }
    }

    return substitutor;
  }

  public static boolean isOverloadCheck() {
    return !ourOverloadGuard.currentStack().isEmpty();
  }


  public boolean isTypeArgumentsApplicable() {
    return isTypeArgumentsApplicable(false);
  }

  public boolean isTypeArgumentsApplicable(boolean includeReturnConstraint) {
    final PsiMethod psiMethod = getElement();
    PsiTypeParameter[] typeParams = psiMethod.getTypeParameters();
    if (myTypeArguments != null && typeParams.length != myTypeArguments.length && !PsiUtil.isLanguageLevel7OrHigher(psiMethod)){
      return typeParams.length == 0 && JavaVersionService.getInstance().isAtLeast(psiMethod, JavaSdkVersion.JDK_1_7);
    }
    PsiSubstitutor substitutor = getSubstitutor(includeReturnConstraint);
    return GenericsUtil.isTypeArgumentsApplicable(typeParams, substitutor, getParent());
  }

  protected PsiElement getParent() {
    return myArgumentList != null ? myArgumentList.getParent() : null;
  }

  @Override
  public boolean isValidResult(){
    return super.isValidResult() && isApplicable();
  }

  @NotNull
  @Override
  public PsiMethod getElement(){
    return (PsiMethod)super.getElement();
  }

  @NotNull
  public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy, boolean includeReturnConstraint) {
    return inferTypeArguments(policy, myArgumentList instanceof PsiExpressionList
                                      ? ((PsiExpressionList)myArgumentList).getExpressions()
                                      : PsiExpression.EMPTY_ARRAY, includeReturnConstraint);
  }

  public PsiSubstitutor inferSubstitutorFromArgs(@NotNull ParameterTypeInferencePolicy policy, final PsiExpression[] arguments) {
    if (myTypeArguments == null) {
      return inferTypeArguments(policy, arguments, true);
    }
    else {
      return getSiteSubstitutor();
    }
  }

  @NotNull
  public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy,
                                           @NotNull PsiExpression[] arguments, 
                                           boolean includeReturnConstraint) {
    Map<PsiElement, CurrentCandidateProperties> map = CURRENT_CANDIDATE.get();
    if (map == null) {
      map = new ConcurrentWeakHashMap<PsiElement, CurrentCandidateProperties>();
      CURRENT_CANDIDATE.set(map);
    }
    final PsiMethod method = getElement();
    final CurrentCandidateProperties alreadyThere = 
      map.put(getMarkerList(), new CurrentCandidateProperties(method, super.getSubstitutor(), isVarargs(), !includeReturnConstraint));
    try {
      PsiTypeParameter[] typeParameters = method.getTypeParameters();

      if (!method.hasModifierProperty(PsiModifier.STATIC)) {
        final PsiClass containingClass = method.getContainingClass();
        if (containingClass != null && PsiUtil.isRawSubstitutor(containingClass, mySubstitutor)) {
          Project project = containingClass.getProject();
          JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project);
          return javaPsiFacade.getElementFactory().createRawSubstitutor(mySubstitutor, typeParameters);
        }
      }

      final PsiElement parent = getParent();
      if (parent == null) return PsiSubstitutor.EMPTY;
      Project project = method.getProject();
      JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project);
      return javaPsiFacade.getResolveHelper()
        .inferTypeArguments(typeParameters, method.getParameterList().getParameters(), arguments, mySubstitutor, parent, policy, myLanguageLevel);
    }
    finally {
      if (alreadyThere == null) {
        map.remove(getMarkerList());
      } else {
        map.put(getMarkerList(), alreadyThere);
      }
    }
  }

  protected PsiElement getMarkerList() {
    return myArgumentList;
  }

  public boolean isInferencePossible() {
    return myArgumentList != null && myArgumentList.isValid();
  }


  public static CurrentCandidateProperties getCurrentMethod(PsiElement context) {
    final Map<PsiElement, CurrentCandidateProperties> currentMethodCandidates = CURRENT_CANDIDATE.get();
    return currentMethodCandidates != null ? currentMethodCandidates.get(context) : null;
  }

  public static void updateSubstitutor(PsiElement context, PsiSubstitutor newSubstitutor) {
    final Map<PsiElement, CurrentCandidateProperties> currentMethodCandidates = CURRENT_CANDIDATE.get();
    if (currentMethodCandidates != null) {
      final CurrentCandidateProperties properties = currentMethodCandidates.get(context);
      if (properties != null) {
        properties.setSubstitutor(newSubstitutor);
      }
    }
  }

  public PsiType[] getArgumentTypes() {
    return myArgumentTypes;
  }

  @Override
  public boolean equals(Object o) {
    return super.equals(o) && isVarargs() == ((MethodCandidateInfo)o).isVarargs();
  }

  @Override
  public int hashCode() {
    return 31 * super.hashCode() + (isVarargs() ? 1 : 0);
  }

  public static class CurrentCandidateProperties {
    private final PsiMethod myMethod;
    private PsiSubstitutor mySubstitutor;
    private boolean myVarargs;
    private boolean myApplicabilityCheck;

    public CurrentCandidateProperties(PsiMethod method, PsiSubstitutor substitutor, boolean varargs, boolean applicabilityCheck) {
      myMethod = method;
      mySubstitutor = substitutor;
      myVarargs = varargs;
      myApplicabilityCheck = applicabilityCheck;
    }

    public PsiMethod getMethod() {
      return myMethod;
    }

    public PsiSubstitutor getSubstitutor() {
      return mySubstitutor;
    }

    public void setSubstitutor(PsiSubstitutor substitutor) {
      mySubstitutor = substitutor;
    }

    public boolean isVarargs() {
      return myVarargs;
    }

    public void setVarargs(boolean varargs) {
      myVarargs = varargs;
    }

    public boolean isApplicabilityCheck() {
      return myApplicabilityCheck;
    }

    public void setApplicabilityCheck(boolean applicabilityCheck) {
      myApplicabilityCheck = applicabilityCheck;
    }
  }
  
  public static class ApplicabilityLevel {
    public static final int NOT_APPLICABLE = 1;
    public static final int VARARGS = 2;
    public static final int FIXED_ARITY = 3;
  }

  @MagicConstant(intValues = {ApplicabilityLevel.NOT_APPLICABLE, ApplicabilityLevel.VARARGS, ApplicabilityLevel.FIXED_ARITY})
  public @interface ApplicabilityLevelConstant {
  }
}
