package org.eclipse.scout.sdk.util.signature;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.Flags;
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;
import org.eclipse.scout.commons.CompareUtility;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.sdk.util.internal.SdkUtilActivator;
import org.eclipse.scout.sdk.util.internal.sigcache.SignatureCache;
import org.eclipse.scout.sdk.util.signature.internal.TypeGenericMapping;
import org.eclipse.scout.sdk.util.type.TypeUtility;

public final class SignatureUtility {

  private static final Pattern QUALIFIED_SIG_REGEX = Pattern.compile("^([\\+\\[]*)([^\\<\\(\\;]*)(.*)$");
  private static final Pattern SIG_REPLACEMENT_REGEX = Pattern.compile("[\\.\\$]{1}");
  private static final Pattern PARAM_SIG_REPLACEMENT_REGEX = Pattern.compile("^([^\\:]*)\\:(.*)$");
  private static final Pattern SIG_END = Pattern.compile("(^.*)\\;$");
  public static final Pattern DOLLAR_REPLACEMENT_REGEX = Pattern.compile("\\$");

  /**
   * Character constant indicating an arbitrary array type in a signature.
   * Value is <code>'|'</code>.
   */
  public static final char C_ARBITRARY_ARRAY = '|';

  /**
   * Kind constant for a arbitrary array signature.
   * 
   * @see #getTypeSignatureKind(String)
   * @since 3.0
   */
  public static final int ARBITRARY_ARRAY_SIGNATURE = 29;

  private SignatureUtility() {
  }

  public static String unboxPrimitiveSignature(String signature) {
    if (Signature.getTypeSignatureKind(signature) == Signature.BASE_TYPE_SIGNATURE) {
      if (Signature.SIG_BOOLEAN.equals(signature)) {
        signature = SignatureCache.createTypeSignature(Boolean.class.getName());
      }
      else if (Signature.SIG_BYTE.equals(signature)) {
        signature = SignatureCache.createTypeSignature(Byte.class.getName());
      }
      else if (Signature.SIG_CHAR.equals(signature)) {
        signature = SignatureCache.createTypeSignature(Character.class.getName());
      }
      else if (Signature.SIG_DOUBLE.equals(signature)) {
        signature = SignatureCache.createTypeSignature(Double.class.getName());
      }
      else if (Signature.SIG_FLOAT.equals(signature)) {
        signature = SignatureCache.createTypeSignature(Float.class.getName());
      }
      else if (Signature.SIG_INT.equals(signature)) {
        signature = SignatureCache.createTypeSignature(Integer.class.getName());
      }
      else if (Signature.SIG_LONG.equals(signature)) {
        signature = SignatureCache.createTypeSignature(Long.class.getName());
      }
      else if (Signature.SIG_SHORT.equals(signature)) {
        signature = SignatureCache.createTypeSignature(Short.class.getName());
      }
    }
    return signature;
  }

  /**
   * To get the signature kind of the given signature. If a signature starts with '|' it is a arbitrary array signature
   * otherwise see {@link Signature#getTypeSignatureKind(String)}.
   * 
   * @return the signature kind.
   * @see Signature#getTypeSignatureKind(String)
   */
  public static int getTypeSignatureKind(String signature) {
    // need a minimum 1 char
    if (signature == null || signature.length() < 1) {
      throw new IllegalArgumentException("signature is null or less than 1 char.");
    }
    char c = signature.charAt(0);
    if (c == C_ARBITRARY_ARRAY) {
      return ARBITRARY_ARRAY_SIGNATURE;
    }
    else {
      return Signature.getTypeSignatureKind(signature);
    }
  }

  private static String quoteRegexSpecialCharacters(String input) {
    input = input.replace("\\", "\\\\");
    input = input.replace(".", "\\.");
    input = input.replace("+", "\\+");
    input = input.replace("?", "\\?");
    input = input.replace("^", "\\^");
    input = input.replace("$", "\\$");
    input = input.replace("[", "\\[");
    input = input.replace("]", "\\]");
    input = input.replace("(", "\\(");
    input = input.replace(")", "\\)");
    input = input.replace("{", "\\{");
    input = input.replace("}", "\\}");
    input = input.replace("*", "\\*");
    input = input.replace("|", "\\|");
    return input;
  }

  public static String getResolvedSignature(String signature, IType signatureOwner) throws CoreException {
    return getResolvedSignature(signature, signatureOwner, null);
  }

  private static boolean endsWith(String stringToSearchIn, char charToFind) {
    return stringToSearchIn != null && !stringToSearchIn.isEmpty() && stringToSearchIn.charAt(stringToSearchIn.length() - 1) == charToFind;
  }

  private static boolean startsWith(String stringToSearchIn, char charToFind) {
    return stringToSearchIn != null && !stringToSearchIn.isEmpty() && stringToSearchIn.charAt(0) == charToFind;
  }

  public static String getResolvedSignature(String signature, IType signatureOwner, IType contextType) throws CoreException {
    Map<String, String> genericParameters = null;
    if (TypeUtility.exists(contextType) && TypeUtility.exists(signatureOwner)) {
      LinkedHashMap<String, ITypeGenericMapping> collector = new LinkedHashMap<String, ITypeGenericMapping>();
      resolveGenericParametersInSuperHierarchy(contextType, new String[0], contextType.newSupertypeHierarchy(new NullProgressMonitor()), collector);
      ITypeGenericMapping mapping = collector.get(signatureOwner.getFullyQualifiedName());
      if (mapping != null) {
        genericParameters = mapping.getParameters();
      }
    }
    if (genericParameters == null) {
      genericParameters = new HashMap<String, String>(0);
    }
    return getResolvedSignature(signatureOwner, genericParameters, signature);
  }

  public static boolean isEqualSignature(String signature1, String signature2) {
    if (signature1 == null && signature2 == null) {
      return true;
    }
    else if (signature1 == null || signature2 == null) {
      return false;
    }
    signature1 = DOLLAR_REPLACEMENT_REGEX.matcher(signature1).replaceAll(".");
    signature2 = DOLLAR_REPLACEMENT_REGEX.matcher(signature2).replaceAll(".");
    return signature1.equals(signature2);
  }

  /**
   * To get the simple type reference name within a context represented by the given importValidator. Every fully
   * qualified type name will be passed to the importValidator to decide if the import is already in use.
   * 
   * @param fullyQualifiedTypeName
   *          e.g. java.lang.String (not a signature).
   * @param importValidator
   *          to evaluate all fully qualified names for create an import and use simple names.
   * @return the simple reference type name in the given validator scope.
   * @throws CoreException
   * @see ScoutSdkUtility#getSimpleTypeRefName(String, IImportValidator)
   */
  public static String getTypeReferenceFromFqn(String fullyQualifiedTypeName, IImportValidator importValidator) throws CoreException {
    return getTypeReference(SignatureCache.createTypeSignature(fullyQualifiedTypeName), importValidator);
  }

  /**
   * @throws CoreException
   * @see {@link ScoutSignature#getTypeReference(String, IType, IType, IImportValidator)}
   */
  public static String getTypeReference(String signature, IImportValidator importValidator) throws CoreException {
    return getTypeReference(signature, null, null, importValidator);
  }

  /**
   * @throws CoreException
   * @see {@link ScoutSignature#getTypeReference(String, IType, IType, IImportValidator)}
   */
  public static String getTypeReference(String signature, IType signatureOwner, IImportValidator validator) throws CoreException {
    return getTypeReference(signature, signatureOwner, null, validator);
  }

  /**
   * <h4>Examples</h4> <xmp>
   * getTypeReferenceImpl("Ljava.lang.String;", typeA, typeA, fullyQualifiedImpValidator)
   * -> java.lang.String
   * getTypeReferenceImpl("QList<?QString>;", typeA, typeA, fullyQualifiedImpValidator)
   * -> java.util.List<? extends java.lang.String>
   * </xmp>
   * 
   * @param signature
   *          fully parameterized signature
   * @param signatureOwner
   *          the owner of the signature used to lookup unresolved types.
   * @param contextType
   *          must be a subtype of signature owner or the owner itself. Used to find generic variables as T. If null and
   *          signature contains generic types the supertype closest to java.lang.Object with the given type parameter
   *          is calculated.
   * @param validator
   *          an import validator to decide simple name vs. fully qualified name.
   * @return the type reference
   * @throws CoreException
   * @see {@link FullyQualifiedValidator}, {@link IImportValidator}, {@link SimpleImportValidator}
   */
  private static String getTypeReference(String signature, IType signatureOwner, IType contextType, IImportValidator validator) throws CoreException {
    StringBuilder sigBuilder = new StringBuilder();
    int arrayCount = 0;
    boolean isArbitraryArray = false;
    switch (getTypeSignatureKind(signature)) {
      case Signature.WILDCARD_TYPE_SIGNATURE:
        sigBuilder.append("?");
        if (signature.length() > 1) {
          sigBuilder.append(" extends ");
          sigBuilder.append(getTypeReference(signature.substring(1), signatureOwner, contextType, validator));
        }
        break;
      case Signature.ARRAY_TYPE_SIGNATURE:
        arrayCount = Signature.getArrayCount(signature);
        sigBuilder.append(getTypeReference(signature.substring(arrayCount), signatureOwner, contextType, validator));
        break;
      case ARBITRARY_ARRAY_SIGNATURE:
        isArbitraryArray = true;
        sigBuilder.append(getTypeReference(signature.substring(1), signatureOwner, contextType, validator));
        break;
      case Signature.BASE_TYPE_SIGNATURE:
        sigBuilder.append(Signature.getSignatureSimpleName(signature));
        break;
      case Signature.TYPE_VARIABLE_SIGNATURE:
        // try to resolve type
        String sig = findTypeParameterSignature(signature, signatureOwner, contextType);
        if (CompareUtility.equals(sig, signature)) {
          sigBuilder.append(sig);
        }
        else {
          sigBuilder.append(getTypeReference(sig, signatureOwner, contextType, validator));
        }
        break;
      default:
        String[] typeArguments = Signature.getTypeArguments(signature);
        signature = Signature.getTypeErasure(signature);
        signature = SIG_REPLACEMENT_REGEX.matcher(signature).replaceAll(".");
        if (startsWith(signature, Signature.C_UNRESOLVED)) {
          // unresolved
          if (signatureOwner != null) {
            String simpleName = Signature.getSignatureSimpleName(signature);
            String referencedTypeSignature = getReferencedTypeSignature(signatureOwner, simpleName, false);
            if (referencedTypeSignature != null) {
              sigBuilder.append(validator.getTypeName(referencedTypeSignature));
            }
          }
          else {
            sigBuilder.append(Signature.toString(signature));
          }
        }
        else {
          // resolved
          sigBuilder.append(validator.getTypeName(signature));
        }
        if (typeArguments != null && typeArguments.length > 0) {
          sigBuilder.append(Signature.C_GENERIC_START);
          for (int i = 0; i < typeArguments.length; i++) {
            if (i > 0) {
              sigBuilder.append(", ");
            }
            sigBuilder.append(getTypeReference(typeArguments[i], signatureOwner, contextType, validator));
          }
          sigBuilder.append(Signature.C_GENERIC_END);
        }
        break;
    }
    for (int i = 0; i < arrayCount; i++) {
      sigBuilder.append("[]");
    }
    if (isArbitraryArray) {
      sigBuilder.append("...");
    }
    return sigBuilder.toString();
  }

  /**
   * To get resolved and substituted generic parameter signatures of the method. The signature starts with
   * {@link ScoutSignature#C_ARBITRARY_ARRAY} if the parameter is a arbitrary array.
   * 
   * @param method
   *          a scout method
   * @return an array of the parameter signatures
   * @throws CoreException
   */
  public static String[] getMethodParameterSignatureResolved(IMethod method) throws CoreException {
    return getMethodParameterSignatureResolved(method, method.getDeclaringType());
  }

  /**
   * To get resolved and substituted generic parameter signatures of the method. The signature starts with
   * {@link ScoutSignature#C_ARBITRARY_ARRAY} if the parameter is a arbitrary array.
   * 
   * @param jdtMethod
   * @param contextType
   *          the type in what context the method appears, used for generic bindings.
   * @return an array of the parameter signatures
   * @throws CoreException
   */
  public static String[] getMethodParameterSignatureResolved(IMethod jdtMethod, IType contextType) throws CoreException {
    LinkedHashMap<String, ITypeGenericMapping> genericMapperCollector = new LinkedHashMap<String, ITypeGenericMapping>();
    resolveGenericParametersInSuperHierarchy(contextType, new String[0], contextType.newSupertypeHierarchy(new NullProgressMonitor()), genericMapperCollector);
    ITypeGenericMapping mapping = genericMapperCollector.get(jdtMethod.getDeclaringType().getFullyQualifiedName());
    Map<String, String> parameters = null;
    if (mapping != null) {
      parameters = mapping.getParameters();
    }
    else {
      parameters = new HashMap<String, String>(0);
    }
    return getMethodParameterSignatureResolved(jdtMethod, parameters);
  }

  public static String[] getMethodParameterSignatureResolved(IMethod jdtMethod, Map<String, String> generics) throws CoreException {
    String[] methodParameterSignature = getMethodParameterSignature(jdtMethod);
    IType methodOwnerType = jdtMethod.getDeclaringType();
    for (int i = 0; i < methodParameterSignature.length; i++) {
      methodParameterSignature[i] = getResolvedSignature(methodOwnerType, generics, methodParameterSignature[i]); // TODOmethodParameterSignature[i], methodOwnerType, contextType);
    }
    return methodParameterSignature;
  }

  /**
   * The get parameter signatures of the given method. The signature starts with
   * {@link ScoutSignature#C_ARBITRARY_ARRAY} if the parameter is a arbitrary array. <h5>NOTE:</h5> <b>generic types are
   * not resolved use {@link ScoutSignature#getMethodParameterSignatureResolved(IMethod)} to get resolved and
   * generic substituted parameter signature</b><br>
   * <br>
   * 
   * @param method
   * @return
   * @throws JavaModelException
   */
  public static String[] getMethodParameterSignature(IMethod method) throws JavaModelException {
    String[] paramNames = method.getParameterNames();
    String[] paramSignatures = Arrays.copyOf(method.getParameterTypes(), method.getParameterTypes().length);
    // check for ... array on last parameter
    if (paramSignatures != null && paramSignatures.length > 0) {
      String lastSig = paramSignatures[paramSignatures.length - 1];
      String lastParamName = paramNames[paramNames.length - 1];
      if (Signature.getTypeSignatureKind(lastSig) == Signature.ARRAY_TYPE_SIGNATURE) {
        String source = method.getSource();
        if (source != null) {
          String regex = method.getElementName() + "\\s*\\(.*([\\.]{3})\\s*" + lastParamName + "\\s*\\)";
          if (Pattern.compile(regex, Pattern.MULTILINE).matcher(source).find()) {
            paramSignatures[paramSignatures.length - 1] = lastSig.replaceFirst("^\\[", "|");
          }
        }
      }
    }
    return paramSignatures;
  }

  /**
   * To get resolved return type signature of the given method. Generic types are substituted within the method context.
   * 
   * @param method
   *          a scout method
   * @return an array of the parameter signatures
   * @throws CoreException
   */
  public static String getReturnTypeSignatureResolved(IMethod method, IType contextType) throws CoreException {
    String returnTypeSignature = method.getReturnType();
    IType methodDeclaringType = method.getDeclaringType();
    returnTypeSignature = getResolvedSignature(returnTypeSignature, methodDeclaringType, contextType);
    return returnTypeSignature;
  }

  private static String ensureSourceTypeParametersAreCorrect(String signature, IType signatureOwner) throws JavaModelException {
    if (!TypeUtility.exists(signatureOwner) || signatureOwner.isBinary()) {
      return signature;
    }
    else {
      ITypeParameter[] typeParameters = signatureOwner.getTypeParameters();
      if (typeParameters != null && typeParameters.length > 0) {
        for (ITypeParameter tp : typeParameters) {
          if (CompareUtility.equals(tp.getElementName(), Signature.getSignatureSimpleName(signature))) {
            return new StringBuilder().append(Signature.C_TYPE_VARIABLE).append(tp.getElementName()).append(Signature.C_SEMICOLON).toString();
          }
        }
      }
      return signature;
    }
  }

  /**
   * returns a unique identifier of a scout method. The identifier looks like
   * 'methodname(param1Signature,param2Signature)'.
   * 
   * @param method
   * @return
   * @throws CoreException
   */
  public static String getMethodIdentifier(IMethod method) throws CoreException {
    StringBuilder methodIdBuilder = new StringBuilder();
    methodIdBuilder.append(method.getElementName());
    methodIdBuilder.append("(");
    String[] resolvedParamSignatures = getMethodParameterSignatureResolved(method, method.getDeclaringType());
    for (int i = 0; i < resolvedParamSignatures.length; i++) {
      methodIdBuilder.append(resolvedParamSignatures[i]);
      if (i + 1 < resolvedParamSignatures.length) {
        methodIdBuilder.append(",");
      }
    }
    methodIdBuilder.append(")");
    return methodIdBuilder.toString();
  }

  private static String findTypeParameterSignature(String typeParameterSignature, IType signatureOwner, IType contextType) throws CoreException {
    if (!TypeUtility.exists(contextType) || !TypeUtility.exists(signatureOwner)) {
      return typeParameterSignature;
    }
    String paramTypeName = Signature.getSignatureSimpleName(typeParameterSignature);

    List<IType> hierarchyList = new ArrayList<IType>();
    if (contextType != null) {
      ITypeHierarchy superTypeHierarchy = contextType.newSupertypeHierarchy(null);
      IType visitorType = contextType;
      while (visitorType != null && !visitorType.equals(signatureOwner)) {
        hierarchyList.add(0, visitorType);
        visitorType = superTypeHierarchy.getSuperclass(visitorType);
      }
    }

    // check requested Parameter
    String[] ownerParameterSignatures = signatureOwner.getTypeParameterSignatures();
    int parameterIndex = -1;
    for (int i = 0; i < ownerParameterSignatures.length; i++) {
      String paramSig = ownerParameterSignatures[i];
      String paramName = PARAM_SIG_REPLACEMENT_REGEX.matcher(paramSig).replaceAll("$1");
      paramSig = PARAM_SIG_REPLACEMENT_REGEX.matcher(paramSig).replaceAll("$2");
      if (contextType == null) {
        String signature = getResolvedSignature(paramSig, signatureOwner, null);
        return signature;
      }
      else if (paramTypeName.equals(paramName)) {
        parameterIndex = i;
        break;
      }
    }
    if (parameterIndex < 0) {
      return SignatureCache.createTypeSignature(Object.class.getName());
    }
    for (IType hType : hierarchyList) {
      String superClassSignature = hType.getSuperclassTypeSignature();
      if (StringUtility.isNullOrEmpty(superClassSignature)) {
        return SignatureCache.createTypeSignature(Object.class.getName());
      }
      String[] superClassParameterSignatures = Signature.getTypeArguments(superClassSignature);
      if (superClassParameterSignatures.length < parameterIndex + 1) {
        return SignatureCache.createTypeSignature(Object.class.getName());
      }
      else {
        // translate
        String signature = getResolvedSignature(superClassParameterSignatures[parameterIndex], hType, contextType);
        return signature;
      }
    }
    return typeParameterSignature;
  }

  /**
   * Gets the fully qualified name of the given signature.
   * 
   * @param signature
   * @return The fully qualified name of the given signature.
   */
  public static String getFullyQualifiedName(String signature) {
    signature = Signature.getTypeErasure(signature);
    int arrayCount = Signature.getArrayCount(signature);
    if (arrayCount > 0) {
      signature = signature.substring(arrayCount);
    }
    String fqn = Signature.toString(signature);
    return fqn;
  }

  /**
   * Checks if the given signature contains type arguments.
   * 
   * @param sig
   *          The signature to check
   * @return true if the given signature has type arguments, false otherwise.
   */
  public static boolean isGenericSignature(String sig) {
    String[] params = Signature.getTypeArguments(sig);
    return params != null && params.length > 0;
  }

  public static String getQualifiedSignature(String signature, IType jdtType) throws JavaModelException {
    if (getTypeSignatureKind(signature) == Signature.BASE_TYPE_SIGNATURE) {
      return signature;
    }
    else {
      Matcher m = QUALIFIED_SIG_REGEX.matcher(signature);
      if (m.find()) {
        String prefix = m.group(1);
        String simpleSignature = m.group(2);
        String postfix = m.group(3);
        if (startsWith(simpleSignature, Signature.C_UNRESOLVED)) {
          String simpleName = Signature.getSignatureSimpleName(simpleSignature + Signature.C_SEMICOLON);
          String referencedTypeSignature = getReferencedTypeSignature(jdtType, simpleName, false);
          if (referencedTypeSignature != null) {
            simpleSignature = SIG_END.matcher(referencedTypeSignature).replaceAll("$1");
            signature = prefix + simpleSignature + postfix;
          }
        }
        String[] typeArguments = Signature.getTypeArguments(signature);

        for (String typeArg : typeArguments) {
          signature.replaceFirst("^([^<]*\\<.*)(" + quoteRegexSpecialCharacters(typeArg) + ")(.*)$", "$1" + getQualifiedSignature(typeArg, jdtType) + "$3");
        }
      }
      else {
        SdkUtilActivator.logWarning("could not qualify types of signature '" + signature + "'");
      }
      return signature;
    }
  }

  public static void resolveGenericParametersInSuperHierarchy(String signature, String superTypeSignature, String[] interfaceSignatures, LinkedHashMap<String/*fullyQualifiedName*/, ITypeGenericMapping> collector) throws CoreException {
    resolveGenericParametersInSuperHierarchy(signature, new String[0], superTypeSignature, interfaceSignatures, collector);
  }

  private static void resolveGenericParametersInSuperHierarchy(String signature, String[] parameterSignatures, String superTypeSignature, String[] interfaceSignatures, LinkedHashMap<String/*fullyQualifiedName*/, ITypeGenericMapping> collector) throws CoreException {
    TypeGenericMapping typeDesc = new TypeGenericMapping(Signature.getSignatureQualifier(signature) + "." + Signature.getSignatureSimpleName(signature));
    String[] localParameterSignatures = Signature.getTypeParameters(signature);
    if (localParameterSignatures.length > 0) {
      for (int i = 0; i < localParameterSignatures.length; i++) {
        typeDesc.addParameter(Signature.getSignatureSimpleName(localParameterSignatures[i]), parameterSignatures[i]);
      }
    }
    collector.put(typeDesc.getFullyQualifiedName(), typeDesc);

    // super type
    if (superTypeSignature != null) {
      String[] superTypeParameterSignatures = new String[0];
      IType superType = TypeUtility.getTypeBySignature(superTypeSignature);
      if (TypeUtility.exists(superType)) {
        String[] typeParameters = Signature.getTypeArguments(superTypeSignature);
        superTypeParameterSignatures = new String[typeParameters.length];
        for (int i = 0; i < typeParameters.length; i++) {//String typeParameter: typeParameters){
          if (Signature.getTypeSignatureKind(typeParameters[i]) == Signature.TYPE_VARIABLE_SIGNATURE) {
            superTypeParameterSignatures[i] = typeDesc.getParameterSignature(Signature.getSignatureSimpleName(typeParameters[i]));
          }
          else {
            superTypeParameterSignatures[i] = typeParameters[i];
          }
        }
        resolveGenericParametersInSuperHierarchy(superType, superTypeParameterSignatures, superType.newSupertypeHierarchy(new NullProgressMonitor()), collector);
      }
    }
    // interfaces
    if (interfaceSignatures != null) {
      for (String interfaceSignature : interfaceSignatures) {
        IType interfaceType = TypeUtility.getTypeBySignature(interfaceSignature);
        if (TypeUtility.exists(interfaceType)) {
          String[] typeParameters = Signature.getTypeParameters(interfaceSignature);
          String[] intefaceTypeParameterSignatures = new String[typeParameters.length];
          for (int i = 0; i < typeParameters.length; i++) {//String typeParameter: typeParameters){
            if (Signature.getTypeSignatureKind(typeParameters[i]) == Signature.TYPE_VARIABLE_SIGNATURE) {
              intefaceTypeParameterSignatures[i] = typeDesc.getParameterSignature(Signature.getSignatureSimpleName(typeParameters[i]));
            }
          }
          resolveGenericParametersInSuperHierarchy(interfaceType, intefaceTypeParameterSignatures, interfaceType.newSupertypeHierarchy(new NullProgressMonitor()), collector);
        }
      }
    }
  }

  public static String resolveGenericParameterInSuperHierarchy(IType startType, ITypeHierarchy superHierarchy, String genericDefiningSuperTypeFqn, String paramName) throws CoreException {
    LinkedHashMap<String, ITypeGenericMapping> collector = new LinkedHashMap<String, ITypeGenericMapping>();
    resolveGenericParametersInSuperHierarchy(startType, new String[]{}, superHierarchy, collector);
    ITypeGenericMapping genericMapping = collector.get(genericDefiningSuperTypeFqn);
    if (genericMapping != null) {
      return genericMapping.getParameterSignature(paramName);
    }
    return null;
  }

  public static void resolveGenericParametersInSuperHierarchy(IType type, ITypeHierarchy hierarchy, LinkedHashMap<String/*fullyQualifiedName*/, ITypeGenericMapping> collector) throws CoreException {
    resolveGenericParametersInSuperHierarchy(type, new String[]{}, hierarchy, collector);
  }

  private static void resolveGenericParametersInSuperHierarchy(IType type, String[] parameterSignatures, ITypeHierarchy hierarchy, LinkedHashMap<String/*fullyQualifiedName*/, ITypeGenericMapping> collector) throws CoreException {
    if (!TypeUtility.exists(type)) {
      return;
    }
    TypeGenericMapping typeDesc = new TypeGenericMapping(type.getFullyQualifiedName());
    ITypeParameter[] typeParameters = type.getTypeParameters();
    HashMap<String, String> paramsUnresolved = new HashMap<String, String>(typeParameters.length);
    for (ITypeParameter par : typeParameters) {
      String[] boundsSignatures = par.getBoundsSignatures();
      if (boundsSignatures != null && boundsSignatures.length > 0) {
        paramsUnresolved.put(par.getElementName(), par.getBoundsSignatures()[0]);
      }
    }

    for (int i = 0; i < typeParameters.length; i++) {
      if (parameterSignatures.length > i) {
        typeDesc.addParameter(typeParameters[i].getElementName(), parameterSignatures[i]);
      }
      else {
        String[] boundsSignatures = typeParameters[i].getBoundsSignatures();
        if (boundsSignatures != null && boundsSignatures.length > 0) {
          typeDesc.addParameter(typeParameters[i].getElementName(), getResolvedSignature(type, paramsUnresolved, boundsSignatures[0]));
        }
        else {
          typeDesc.addParameter(typeParameters[i].getElementName(), SignatureCache.createTypeSignature(Object.class.getName()));
        }
      }
    }
    collector.put(typeDesc.getFullyQualifiedName(), typeDesc);
    // super class
    if (!Flags.isInterface(type.getFlags())) {
      String superclassTypeSignature = type.getSuperclassTypeSignature();
      if (StringUtility.hasText(superclassTypeSignature)) {
        String[] superParameterSigs = Signature.getTypeArguments(superclassTypeSignature);
        String[] superclassParameterSignatures = new String[superParameterSigs.length];
        for (int i = 0; i < superclassParameterSignatures.length; i++) {
          String resolvedSignature = getResolvedSignature(type, typeDesc.getParameters(), superParameterSigs[i]);
          String signatureQualifier = Signature.getSignatureQualifier(resolvedSignature);
          String signatureSimpleName = Signature.getSignatureSimpleName(resolvedSignature);
          if (StringUtility.isNullOrEmpty(signatureQualifier) && typeDesc.getParameterSignature(signatureSimpleName) != null) {
            // resolve parameter
            resolvedSignature = typeDesc.getParameterSignature(signatureSimpleName);
          }
          superclassParameterSignatures[i] = resolvedSignature;
        }
        resolveGenericParametersInSuperHierarchy(hierarchy.getSuperclass(type), superclassParameterSignatures, hierarchy, collector);
      }
    }
    // interfaces
    String[] superInterfaceTypeSignatures = type.getSuperInterfaceTypeSignatures();
    for (String superInterfaceTypeSignature : superInterfaceTypeSignatures) {
      String[] interfaceParameterSigs = Signature.getTypeArguments(superInterfaceTypeSignature);
      String[] interfaceParameterSignatures = new String[interfaceParameterSigs.length];

      for (int i = 0; i < interfaceParameterSignatures.length; i++) {
        String resolvedSignature = getResolvedSignature(type, typeDesc.getParameters(), interfaceParameterSigs[i]);
        String signatureQualifier = Signature.getSignatureQualifier(resolvedSignature);
        String signatureSimpleName = Signature.getSignatureSimpleName(resolvedSignature);
        if (StringUtility.isNullOrEmpty(signatureQualifier) && typeDesc.getParameterSignature(signatureSimpleName) != null) {
          // resolve parameter
          resolvedSignature = typeDesc.getParameterSignature(signatureSimpleName);
        }
        interfaceParameterSignatures[i] = resolvedSignature;
      }
      resolveGenericParametersInSuperHierarchy(TypeUtility.getTypeBySignature(superInterfaceTypeSignature), interfaceParameterSignatures, hierarchy, collector);
    }

  }

  public static String getResolvedSignature(IType contextType, Map<String, String> parameterSignatures, String unresolvedSignature) throws JavaModelException {
    StringBuilder sigBuilder = new StringBuilder();
    unresolvedSignature = ensureSourceTypeParametersAreCorrect(unresolvedSignature, contextType);
    switch (getTypeSignatureKind(unresolvedSignature)) {
      case Signature.WILDCARD_TYPE_SIGNATURE:
        sigBuilder.append(unresolvedSignature.charAt(0));
        if (unresolvedSignature.length() > 1) {
          sigBuilder.append(getResolvedSignature(contextType, parameterSignatures, unresolvedSignature.substring(1)));
        }
        break;
      case Signature.ARRAY_TYPE_SIGNATURE:
        sigBuilder.append(Signature.C_ARRAY);
        sigBuilder.append(getResolvedSignature(contextType, parameterSignatures, unresolvedSignature.substring(1)));
        break;
      case ARBITRARY_ARRAY_SIGNATURE:
        sigBuilder.append(C_ARBITRARY_ARRAY);
        sigBuilder.append(getResolvedSignature(contextType, parameterSignatures, unresolvedSignature.substring(1)));
        break;
      case Signature.BASE_TYPE_SIGNATURE:
        if (endsWith(unresolvedSignature, Signature.C_NAME_END)) {
          unresolvedSignature = unresolvedSignature.substring(0, unresolvedSignature.length() - 1);
        }
        sigBuilder.append(unresolvedSignature);
        break;
      case Signature.TYPE_VARIABLE_SIGNATURE:
        // try to resolve type
        String sig = parameterSignatures.get(Signature.getSignatureSimpleName(unresolvedSignature));
        if (startsWith(sig, Signature.C_UNRESOLVED) && TypeUtility.exists(contextType)) {
          String simpleName = Signature.getSignatureSimpleName(sig);
          String referencedTypeSignature = getReferencedTypeSignature(contextType, simpleName, false);
          if (referencedTypeSignature != null) {
            sig = referencedTypeSignature;
          }
        }
        sigBuilder.append(sig);
        break;
      case Signature.CLASS_TYPE_SIGNATURE:
        String[] typeArguments = Signature.getTypeArguments(unresolvedSignature);
        unresolvedSignature = Signature.getTypeErasure(unresolvedSignature);
        unresolvedSignature = SIG_REPLACEMENT_REGEX.matcher(unresolvedSignature).replaceAll(".");
        if (startsWith(unresolvedSignature, Signature.C_UNRESOLVED)) {
          // unresolved
          if (StringUtility.hasText(Signature.getSignatureQualifier(unresolvedSignature))) {
            // kind of a qualified signature
            IType t = TypeUtility.getTypeBySignature(unresolvedSignature);
            if (TypeUtility.exists(t)) {
              unresolvedSignature = SignatureCache.createTypeSignature(t.getFullyQualifiedName().replace('$', '.'));
            }
          }
          else if (TypeUtility.exists(contextType)) {
            String simpleName = Signature.getSignatureSimpleName(unresolvedSignature);
            String referencedTypeSignature = getReferencedTypeSignature(contextType, simpleName, false);
            if (referencedTypeSignature != null) {
              unresolvedSignature = referencedTypeSignature;
            }
          }
        }
        if (endsWith(unresolvedSignature, Signature.C_NAME_END)) {
          unresolvedSignature = unresolvedSignature.substring(0, unresolvedSignature.length() - 1);
        }
        sigBuilder.append(unresolvedSignature);
        if (typeArguments != null && typeArguments.length > 0) {
          sigBuilder.append(Signature.C_GENERIC_START);
          for (int i = 0; i < typeArguments.length; i++) {
            sigBuilder.append(getResolvedSignature(contextType, parameterSignatures, typeArguments[i]));
          }
          sigBuilder.append(Signature.C_GENERIC_END);
        }
        sigBuilder.append(Signature.C_NAME_END);
        break;
      default:
        SdkUtilActivator.logWarning("unhandled signature type: '" + Signature.getTypeSignatureKind(unresolvedSignature) + "'");
        break;
    }
    return sigBuilder.toString();
  }

  /**
   * @return The resolved signature
   * @see TypeUtility#getReferencedTypeFqn(IType, String, boolean)
   */
  public static String getReferencedTypeSignature(IType declaringType, String typeName, boolean searchOnClassPath) throws JavaModelException {
    String referencedTypeFqn = TypeUtility.getReferencedTypeFqn(declaringType, typeName, searchOnClassPath);
    if (referencedTypeFqn != null) {
      return SignatureCache.createTypeSignature(referencedTypeFqn);
    }
    return null;
  }
}
