/*
 * Copyright (C) 2010 Google Inc.
 *
 * 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.google.doclava;

import com.google.clearsilver.jsilver.data.Data;

import java.util.*;

public class TypeInfo implements Resolvable {
  public static final Set<String> PRIMITIVE_TYPES = Collections.unmodifiableSet(
      new HashSet<String>(Arrays.asList("boolean", "byte", "char", "double", "float", "int",
      "long", "short", "void")));

  public TypeInfo(boolean isPrimitive, String dimension, String simpleTypeName,
      String qualifiedTypeName, ClassInfo cl) {
    mIsPrimitive = isPrimitive;
    mDimension = dimension;
    mSimpleTypeName = simpleTypeName;
    mQualifiedTypeName = qualifiedTypeName;
    mClass = cl;
  }

  public TypeInfo(String typeString) {
    // VarArgs
    if (typeString.endsWith("...")) {
      typeString = typeString.substring(0, typeString.length() - 3);
    }

    // Generic parameters
    int extendsPos = typeString.indexOf(" extends ");
    int paramStartPos = typeString.indexOf('<');
    if (paramStartPos > -1 && (extendsPos == -1 || paramStartPos < extendsPos)) {
      ArrayList<TypeInfo> generics = new ArrayList<TypeInfo>();
      int paramEndPos = 0;

      int entryStartPos = paramStartPos + 1;
      int bracketNesting = 0;
      for (int i = entryStartPos; i < typeString.length(); i++) {
        char c = typeString.charAt(i);
        if (c == ',' && bracketNesting == 0) {
          String entry = typeString.substring(entryStartPos, i).trim();
          TypeInfo info = new TypeInfo(entry);
          generics.add(info);
          entryStartPos = i + 1;
        } else if (c == '<') {
          bracketNesting++;
        } else if (c == '>') {
          bracketNesting--;
          // Once bracketNesting goes negative, we've found the closing angle bracket
          if (bracketNesting < 0) {
            paramEndPos = i;
            break;
          }
        }
      }

      TypeInfo info = new TypeInfo(typeString.substring(entryStartPos, paramEndPos).trim());
      generics.add(info);
      addResolution(new Resolution("variability", "", null));

      mTypeArguments = generics;

      if (paramEndPos < typeString.length() - 1) {
        typeString = typeString.substring(0,paramStartPos) + typeString.substring(paramEndPos + 1);
      } else {
        typeString = typeString.substring(0,paramStartPos);
      }
    }

    // The previous extends may have been within the generic type parameters which we don't
    // actually care about and were removed from the type string above
    extendsPos = typeString.indexOf(" extends ");
    if (extendsPos > -1) {
      ArrayList<TypeInfo> extendsBounds = new ArrayList<>();
      int entryStartPos = extendsPos + 9;
      int bracketNesting = 0;
      for (int i = entryStartPos; i < typeString.length(); i++) {
        char c = typeString.charAt(i);
        if (c == '&' && bracketNesting == 0) {
          String entry = typeString.substring(entryStartPos, i).trim();
          TypeInfo info = new TypeInfo(entry);
          extendsBounds.add(info);
          entryStartPos = i + 1;
        } else if (c == '<') {
          bracketNesting++;
        } else if (c == '>') {
          bracketNesting--;
        }
      }
      TypeInfo info = new TypeInfo(typeString.substring(entryStartPos, typeString.length()).trim());
      extendsBounds.add(info);
      mExtendsBounds = extendsBounds;
      typeString = typeString.substring(0, extendsPos);
    }

    int pos = typeString.indexOf('[');
    if (pos > -1) {
      mDimension = typeString.substring(pos);
      typeString = typeString.substring(0, pos);
    } else {
      mDimension = "";
    }

    if (PRIMITIVE_TYPES.contains(typeString)) {
      mIsPrimitive = true;
      mSimpleTypeName = typeString;
      mQualifiedTypeName = typeString;
    } else {
      mQualifiedTypeName = typeString;
      pos = typeString.lastIndexOf('.');
      if (pos > -1) {
        mSimpleTypeName = typeString.substring(pos + 1);
      } else {
        mSimpleTypeName = typeString;
      }
    }
  }

  /**
   * Copy Constructor.
   */
  private TypeInfo(TypeInfo other) {
    mIsPrimitive = other.isPrimitive();
    mIsTypeVariable = other.isTypeVariable();
    mIsWildcard = other.isWildcard();
    mDimension = other.dimension();
    mSimpleTypeName = other.simpleTypeName();
    mQualifiedTypeName = other.qualifiedTypeName();
    mClass = other.asClassInfo();
    if (other.typeArguments() != null) {
      mTypeArguments = new ArrayList<TypeInfo>(other.typeArguments());
    }
    if (other.superBounds() != null) {
      mSuperBounds = new ArrayList<TypeInfo>(other.superBounds());
    }
    if (other.extendsBounds() != null) {
      mExtendsBounds = new ArrayList<TypeInfo>(other.extendsBounds());
    }
    mFullName = other.fullName();
  }

  /**
   * Returns this type as a {@link ClassInfo} if it represents a class or
   * interface.
   */
  public ClassInfo asClassInfo() {
    if (!mResolvedClass) {
      mResolvedClass = true;
      if (mClass == null && !mIsPrimitive && !mIsTypeVariable && !mIsWildcard) {
        mClass = Converter.obtainClass(qualifiedTypeName());
      }
    }
    return mClass;
  }

  public boolean isPrimitive() {
    return mIsPrimitive;
  }

  public String dimension() {
    return mDimension;
  }

  public void setDimension(String dimension) {
      mDimension = dimension;
  }

  public String simpleTypeName() {
    return mSimpleTypeName;
  }

  public String qualifiedTypeName() {
    return mQualifiedTypeName;
  }

  public String fullName() {
    if (mFullName != null) {
      return mFullName;
    } else {
      return fullName(new HashSet<String>());
    }
  }

  public static String typeArgumentsName(ArrayList<TypeInfo> args, HashSet<String> typeVars) {
    String result = "<";

    int i = 0;
    for (TypeInfo arg : args) {
      result += arg.fullName(typeVars);
      if (i != (args.size()-1)) {
        result += ", ";
      }
      i++;
    }
    result += ">";
    return result;
  }

  public String fullName(HashSet<String> typeVars) {
    mFullName = fullNameNoDimension(typeVars) + mDimension;
    return mFullName;
  }

  public String fullNameNoBounds(HashSet<String> typeVars) {
    return fullNameNoDimensionNoBounds(typeVars) + mDimension;
  }

  // don't recurse forever with the parameters. This handles
  // Enum<K extends Enum<K>>
  private boolean checkRecurringTypeVar(HashSet<String> typeVars) {
    if (mIsTypeVariable) {
      if (typeVars.contains(mQualifiedTypeName)) {
        return true;
      }
      typeVars.add(mQualifiedTypeName);
    }
    return false;
  }

  private String fullNameNoDimensionNoBounds(HashSet<String> typeVars) {
    String fullName = null;
    if (checkRecurringTypeVar(typeVars)) {
      return mQualifiedTypeName;
    }
    /*
     * if (fullName != null) { return fullName; }
     */
    fullName = mQualifiedTypeName;
    if (mTypeArguments != null && !mTypeArguments.isEmpty()) {
      fullName += typeArgumentsName(mTypeArguments, typeVars);
    }
    return fullName;
  }

  public String fullNameNoDimension(HashSet<String> typeVars) {
    String fullName = null;
    if (checkRecurringTypeVar(typeVars)) {
      return mQualifiedTypeName;
    }
    fullName = fullNameNoDimensionNoBounds(typeVars);
    if (mTypeArguments == null || mTypeArguments.isEmpty()) {
       if (mSuperBounds != null && !mSuperBounds.isEmpty()) {
        for (TypeInfo superBound : mSuperBounds) {
            if (superBound == mSuperBounds.get(0)) {
                fullName += " super " + superBound.fullNameNoBounds(typeVars);
            } else {
                fullName += " & " + superBound.fullNameNoBounds(typeVars);
            }
        }
      } else if (mExtendsBounds != null && !mExtendsBounds.isEmpty()) {
        for (TypeInfo extendsBound : mExtendsBounds) {
            if (extendsBound == mExtendsBounds.get(0)) {
                fullName += " extends " + extendsBound.fullNameNoBounds(typeVars);
            } else {
                fullName += " & " + extendsBound.fullNameNoBounds(typeVars);
            }
        }
      }
    }
    return fullName;
  }

  public ArrayList<TypeInfo> typeArguments() {
    return mTypeArguments;
  }

  public void makeHDF(Data data, String base) {
    makeHDFRecursive(data, base, false, false, new HashSet<String>());
  }

  public void makeQualifiedHDF(Data data, String base) {
    makeHDFRecursive(data, base, true, false, new HashSet<String>());
  }

  public void makeHDF(Data data, String base, boolean isLastVararg, HashSet<String> typeVariables) {
    makeHDFRecursive(data, base, false, isLastVararg, typeVariables);
  }

  public void makeQualifiedHDF(Data data, String base, HashSet<String> typeVariables) {
    makeHDFRecursive(data, base, true, false, typeVariables);
  }

  private void makeHDFRecursive(Data data, String base, boolean qualified, boolean isLastVararg,
      HashSet<String> typeVars) {
    String label = qualified ? qualifiedTypeName() : simpleTypeName();
    label += (isLastVararg) ? "..." : dimension();
    data.setValue(base + ".label", label);
    if (mIsTypeVariable || mIsWildcard) {
      // could link to an @param tag on the class to describe this
      // but for now, just don't make it a link
    } else if (!isPrimitive() && mClass != null) {
      if (mClass.isIncluded()) {
        data.setValue(base + ".link", mClass.htmlPage());
        data.setValue(base + ".since", mClass.getSince());
      } else {
        Doclava.federationTagger.tag(mClass);
        if (!mClass.getFederatedReferences().isEmpty()) {
          FederatedSite site = mClass.getFederatedReferences().iterator().next();
          data.setValue(base + ".link", site.linkFor(mClass.htmlPage()));
          data.setValue(base + ".federated", site.name());
        }
      }
    }

    if (mIsTypeVariable) {
      if (typeVars.contains(qualifiedTypeName())) {
        // don't recurse forever with the parameters. This handles
        // Enum<K extends Enum<K>>
        return;
      }
      typeVars.add(qualifiedTypeName());
    }
    if (mTypeArguments != null) {
      TypeInfo.makeHDF(data, base + ".typeArguments", mTypeArguments, qualified, typeVars);
    }
    if (mSuperBounds != null) {
      TypeInfo.makeHDF(data, base + ".superBounds", mSuperBounds, qualified, typeVars);
    }
    if (mExtendsBounds != null) {
      TypeInfo.makeHDF(data, base + ".extendsBounds", mExtendsBounds, qualified, typeVars);
    }
  }

  public static void makeHDF(Data data, String base, ArrayList<TypeInfo> types, boolean qualified,
      HashSet<String> typeVariables) {
    int i = 0;
    for (TypeInfo type : types) {
      type.makeHDFRecursive(data, base + "." + i++, qualified, false, typeVariables);
    }
  }

  public static void makeHDF(Data data, String base, ArrayList<TypeInfo> types, boolean qualified) {
    makeHDF(data, base, types, qualified, new HashSet<String>());
  }

  void setTypeArguments(ArrayList<TypeInfo> args) {
    mTypeArguments = args;
  }

  public void addTypeArgument(TypeInfo arg) {
      if (mTypeArguments == null) {
          mTypeArguments = new ArrayList<TypeInfo>();
      }

      mTypeArguments.add(arg);
  }

  public void setBounds(ArrayList<TypeInfo> superBounds, ArrayList<TypeInfo> extendsBounds) {
    mSuperBounds = superBounds;
    mExtendsBounds = extendsBounds;
  }

  public ArrayList<TypeInfo> superBounds() {
      return mSuperBounds;
  }

  public ArrayList<TypeInfo> extendsBounds() {
      return mExtendsBounds;
  }

  public void setIsTypeVariable(boolean b) {
    mIsTypeVariable = b;
  }

  void setIsWildcard(boolean b) {
    mIsWildcard = b;
  }

  public boolean isWildcard() {
      return mIsWildcard;
  }

  public static HashSet<String> typeVariables(ArrayList<TypeInfo> params) {
    return typeVariables(params, new HashSet<String>());
  }

  static HashSet<String> typeVariables(ArrayList<TypeInfo> params, HashSet<String> result) {
    if (params != null) {
        for (TypeInfo t : params) {
            if (t.mIsTypeVariable) {
                result.add(t.mQualifiedTypeName);
            }
        }
    }
    return result;
  }


  public boolean isTypeVariable() {
    return mIsTypeVariable;
  }

  public void resolveTypeVariables(HashSet<String> variables) {
    if (mExtendsBounds != null) {
      for (TypeInfo bound : mExtendsBounds) {
        if (variables.contains(bound.qualifiedTypeName())) {
          bound.setIsTypeVariable(true);
        }
      }
    }
  }

  public String defaultValue() {
    if (mIsPrimitive) {
      if ("boolean".equals(mSimpleTypeName)) {
        return "false";
      } else {
        return "0";
      }
    } else {
      return "null";
    }
  }

  @Override
  public String toString() {
    String returnString = "";
    returnString +=
        "Primitive?: " + mIsPrimitive + " TypeVariable?: " + mIsTypeVariable + " Wildcard?: "
            + mIsWildcard + " Dimension: " + mDimension + " QualifedTypeName: "
            + mQualifiedTypeName;

    if (mTypeArguments != null) {
      returnString += "\nTypeArguments: ";
      for (TypeInfo tA : mTypeArguments) {
        returnString += tA.qualifiedTypeName() + "(" + tA + ") ";
      }
    }
    if (mSuperBounds != null) {
      returnString += "\nSuperBounds: ";
      for (TypeInfo tA : mSuperBounds) {
        returnString += tA.qualifiedTypeName() + "(" + tA + ") ";
      }
    }
    if (mExtendsBounds != null) {
      returnString += "\nExtendsBounds: ";
      for (TypeInfo tA : mExtendsBounds) {
        returnString += tA.qualifiedTypeName() + "(" + tA + ") ";
      }
    }
    return returnString;
  }

  public void addResolution(Resolution resolution) {
      if (mResolutions == null) {
          mResolutions = new ArrayList<Resolution>();
      }

      mResolutions.add(resolution);
  }

  public void printResolutions() {
      if (mResolutions == null || mResolutions.isEmpty()) {
          return;
      }

      System.out.println("Resolutions for Type " + mSimpleTypeName + ":");
      for (Resolution r : mResolutions) {
          System.out.println(r);
      }
  }

  public boolean resolveResolutions() {
      ArrayList<Resolution> resolutions = mResolutions;
      mResolutions = new ArrayList<Resolution>();

      boolean allResolved = true;
      for (Resolution resolution : resolutions) {
          if ("class".equals(resolution.getVariable())) {
              StringBuilder qualifiedClassName = new StringBuilder();
              InfoBuilder.resolveQualifiedName(resolution.getValue(), qualifiedClassName,
                      resolution.getInfoBuilder());

              // if we still couldn't resolve it, save it for the next pass
              if ("".equals(qualifiedClassName.toString())) {
                  mResolutions.add(resolution);
                  allResolved = false;
              } else {
                  mClass = InfoBuilder.Caches.obtainClass(qualifiedClassName.toString());
              }
          } else if ("variability".equals(resolution.getVariable())) {
              StringBuilder qualifiedClassName = new StringBuilder();
              for (TypeInfo arg : mTypeArguments) {
                InfoBuilder.resolveQualifiedName(arg.simpleTypeName(), qualifiedClassName,
                        resolution.getInfoBuilder());
                arg.setIsTypeVariable(!("".equals(qualifiedClassName.toString())));
              }
          }
      }

      return allResolved;
  }

  /**
   * Copy this TypeInfo, but replace type arguments with those defined in the
   * typeArguments mapping.
   * <p>
   * If the current type is one of the base types in the mapping (i.e. a parameter itself)
   * then this returns the mapped type.
   */
  public TypeInfo getTypeWithArguments(Map<String, TypeInfo> typeArguments) {
    if (typeArguments.containsKey(fullName())) {
      return typeArguments.get(fullName());
    }

    TypeInfo ti = new TypeInfo(this);
    if (typeArguments() != null) {
      ArrayList<TypeInfo> newArgs = new ArrayList<TypeInfo>();
      for (TypeInfo t : typeArguments()) {
        newArgs.add(t.getTypeWithArguments(typeArguments));
      }
      ti.setTypeArguments(newArgs);
    }
    return ti;
  }

  /**
   * Given two TypeInfos that reference the same type, take the first one's type parameters
   * and generate a mapping from their names to the type parameters defined in the second.
   */
  public static Map<String, TypeInfo> getTypeArgumentMapping(TypeInfo generic, TypeInfo typed) {
    Map<String, TypeInfo> map = new HashMap<String, TypeInfo>();
    if (generic != null && generic.typeArguments() != null) {
      for (int i = 0; i < generic.typeArguments().size(); i++) {
        if (typed.typeArguments() != null && typed.typeArguments().size() > i) {
          map.put(generic.typeArguments().get(i).simpleTypeName(), typed.typeArguments().get(i));
        }
      }
    }
    return map;
  }

  /**
   * Given a ClassInfo and a parameterized TypeInfo, take the class's raw type's type parameters
   * and generate a mapping from their names to the type parameters defined in the TypeInfo.
   */
  public static Map<String, TypeInfo> getTypeArgumentMapping(ClassInfo cls, TypeInfo typed) {
    return getTypeArgumentMapping(cls.asTypeInfo(), typed);
  }

  private ArrayList<Resolution> mResolutions;

  /** Whether the value of {@code mClass} has been resolved. */
  private boolean mResolvedClass;

  private boolean mIsPrimitive;
  private boolean mIsTypeVariable;
  private boolean mIsWildcard;
  private String mDimension;
  private String mSimpleTypeName;
  private String mQualifiedTypeName;
  private ClassInfo mClass;
  private ArrayList<TypeInfo> mTypeArguments;
  private ArrayList<TypeInfo> mSuperBounds;
  private ArrayList<TypeInfo> mExtendsBounds;
  private String mFullName;
}
