/*
 * 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 paramStartPos = typeString.indexOf('<');
    if (paramStartPos > -1) {
      ArrayList<TypeInfo> generics = new ArrayList<TypeInfo>();
      int paramEndPos = typeString.lastIndexOf('>');
      
      int entryStartPos = paramStartPos + 1;
      int bracketNesting = 0;
      for (int i = entryStartPos; i < paramEndPos; 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--;
        }
      }
     
      TypeInfo info = new TypeInfo(typeString.substring(entryStartPos, paramEndPos).trim());
      generics.add(info);
      
      mTypeArguments = generics;
      
      if (paramEndPos < typeString.length() - 1) {
        typeString = typeString.substring(0,paramStartPos) + typeString.substring(paramEndPos + 1);
      } else {
        typeString = typeString.substring(0,paramStartPos);
      }
    }
    
    // Dimensions
    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();
  }

  public ClassInfo asClassInfo() {
    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);
  }

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

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

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

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

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

  public boolean isWildcard() {
      return mIsWildcard;
  }

  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 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());
              }
          }
      }

      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>();
    for (int i = 0; i < generic.typeArguments().size(); i++) {
      if (typed.typeArguments() != null && typed.typeArguments().size() > i) {
        map.put(generic.typeArguments().get(i).fullName(), 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;

  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;
}
