/*
 * Copyright 2008 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.gwt.tools.apichecker;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JAbstractMethod;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JField;
import com.google.gwt.core.ext.typeinfo.JMethod;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Encapsulates an API class.
 */
final class ApiClass implements Comparable<ApiClass>, ApiElement {
  /**
   * Enum for indexing the common storage used for methods and constructors
   * 
   */
  public static enum MethodType {
    CONSTRUCTOR, METHOD;
  }

  private HashMap<String, ApiField> apiFields = null;

  /**
   * TODO (amitmanjhi): Toby felt that combining structures for storing
   * MethodType and Constructors was unnecessary. In particular, the hashMap of
   * name#args -> object is meaningless for constructor, since name is empty for
   * constructors. Make it separate.
   * 
   * In addition, the current method fails when constructors or methods accept
   * variable arguments. In future, just index everything by name [and not add
   * the number of arguments that they accept].
   */

  /**
   * 2 entries in the list: one for CONSTRUCTOR, and the other for METHOD. Each
   * entry is a mapping from MethodName#args to a set of ApiAbstractMethod
   */
  private EnumMap<MethodType, Map<String, Set<ApiAbstractMethod>>> apiMembersByName = null;

  private final ApiPackage apiPackage;
  private final JClassType classType;

  private final boolean isInstantiableApiClass;
  private final boolean isNotsubclassableApiClass;
  private final boolean isSubclassableApiClass;
  private final TreeLogger logger;

  ApiClass(JClassType classType, ApiPackage apiPackage) {
    this.classType = classType;
    this.apiPackage = apiPackage;
    logger = apiPackage.getApiContainer().getLogger();
    ApiContainer apiContainer = apiPackage.getApiContainer();
    isSubclassableApiClass = apiContainer.isSubclassableApiClass(classType);
    isNotsubclassableApiClass = apiContainer.isNotsubclassableApiClass(classType);
    isInstantiableApiClass = apiContainer.isInstantiableApiClass(classType);
  }

  public int compareTo(ApiClass other) {
    return getName().compareTo(other.getName());
  }
  
  @Override
  public boolean equals(Object o) {
    if (!(o instanceof ApiClass)) {
      return false;
    }
    return this.getName().equals(((ApiClass) o).getName());
  }
  
  public String getRelativeSignature() {
    return classType.getQualifiedSourceName();
  }

  @Override
  public int hashCode() {
    return this.getName().hashCode();
  }

  @Override
  public String toString() {
    return classType.toString();
  }

  String getApiAsString() {
    StringBuffer sb = new StringBuffer();
    sb.append("\t" + getName() + "\n");
    if (apiFields != null) {
      ArrayList<ApiField> apiFieldsList = new ArrayList<ApiField>(
          apiFields.values());
      Collections.sort(apiFieldsList);
      for (ApiField apiField : apiFieldsList) {
        sb.append("\t\t" + apiField.getRelativeSignature() + "\n");
      }
    }
    if (apiMembersByName != null
        && apiMembersByName.get(MethodType.METHOD) != null) {
      for (MethodType method : MethodType.values()) {
        HashSet<ApiAbstractMethod> apiMethodsSet = new HashSet<ApiAbstractMethod>();
        for (Set<ApiAbstractMethod> methodsSets : apiMembersByName.get(method).values()) {
          apiMethodsSet.addAll(methodsSets);
        }
        ArrayList<ApiAbstractMethod> apiMethodsList = new ArrayList<ApiAbstractMethod>(
            apiMethodsSet);
        Collections.sort(apiMethodsList);
        for (ApiAbstractMethod apiMethod : apiMethodsList) {
          sb.append("\t\t" + apiMethod.getRelativeSignature() + "\n");
        }
      }
    }
    return sb.toString();
  }

  ApiField getApiFieldByName(String name) {
    return apiFields.get(name);
  }

  Set<String> getApiFieldNames() {
    if (apiFields == null) {
      initializeApiFields();
    }
    return new HashSet<String>(apiFields.keySet());
  }

  Set<ApiField> getApiFieldsBySet(Set<String> names) {
    Set<ApiField> ret = new HashSet<ApiField>();
    for (String name : names) {
      ret.add(apiFields.get(name));
    }
    return ret;
  }

  Set<String> getApiMemberNames(MethodType type) {
    if (apiMembersByName == null) {
      initializeApiConstructorsAndMethods();
    }
    return new HashSet<String>(apiMembersByName.get(type).keySet());
  }

  Set<ApiAbstractMethod> getApiMembersBySet(Set<String> methodNames,
      MethodType type) {
    Map<String, Set<ApiAbstractMethod>> current = apiMembersByName.get(type);
    Set<ApiAbstractMethod> tempMethods = new HashSet<ApiAbstractMethod>();
    for (String methodName : methodNames) {
      tempMethods.addAll(current.get(methodName));
    }
    return tempMethods;
  }

  Set<ApiAbstractMethod> getApiMethodsByName(String name, MethodType type) {
    return apiMembersByName.get(type).get(name);
  }

  JClassType getClassObject() {
    return classType;
  }

  String getFullName() {
    return classType.getQualifiedSourceName();
  }

  /**
   * compute the modifier changes. check for: (i) added 'final' or 'abstract' or
   * 'static' (ii) removed 'static' or 'non-abstract class made into interface'
   * (if a non-abstract class is made into interface, the client class/interface
   * inheriting from it would need to change)
   */
  List<ApiChange.Status> getModifierChanges(ApiClass newClass) {
    JClassType newClassType = newClass.getClassObject();
    List<ApiChange.Status> statuses = new ArrayList<ApiChange.Status>(5);

    // check for addition of 'final', 'abstract', 'static'
    if (!classType.isFinal() && newClassType.isFinal()) {
      statuses.add(ApiChange.Status.FINAL_ADDED);
    }
    if (!classType.isAbstract() && newClassType.isAbstract()) {
      statuses.add(ApiChange.Status.ABSTRACT_ADDED);
    }
    if (!classType.isStatic() && newClassType.isStatic()) {
      statuses.add(ApiChange.Status.STATIC_ADDED);
    }

    // removed 'static'
    if (classType.isStatic() && !newClassType.isStatic()) {
      statuses.add(ApiChange.Status.STATIC_REMOVED);
    }

    if (!classType.isAbstract() && (newClassType.isInterface() != null)) {
      statuses.add(ApiChange.Status.NONABSTRACT_CLASS_MADE_INTERFACE);
    }
    if (apiPackage.getApiContainer().isSubclassableApiClass(classType)) {
      if ((classType.isClass() != null) && (newClassType.isInterface() != null)) {
        statuses.add(ApiChange.Status.SUBCLASSABLE_API_CLASS_MADE_INTERFACE);
      }
      if ((classType.isInterface() != null) && (newClassType.isClass() != null)) {
        statuses.add(ApiChange.Status.SUBCLASSABLE_API_INTERFACE_MADE_CLASS);
      }
    }
    return statuses;
  }

  String getName() {
    return classType.getName();
  }

  ApiPackage getPackage() {
    return apiPackage;
  }

  void initializeApiFields() {
    apiFields = new HashMap<String, ApiField>();
    List<String> notAddedFields = new ArrayList<String>();
    JField fields[] = getAccessibleFields();
    for (JField field : fields) {
      if (isApiMember(field)) {
        apiFields.put(field.getName(), new ApiField(field, this));
      } else {
        notAddedFields.add(field.toString());
      }
    }
    if (notAddedFields.size() > 0) {
      logger.log(TreeLogger.SPAM, "class " + getName() + " " + ", not adding "
          + notAddedFields.size() + " nonApi fields: " + notAddedFields, null);
    }
  }

  boolean isSubclassableApiClass() {
    return isSubclassableApiClass;
  }

  private JField[] getAccessibleFields() {
    Map<String, JField> fieldsBySignature = new HashMap<String, JField>();
    JClassType tempClassType = classType;
    do {
      JField declaredFields[] = tempClassType.getFields();
      for (JField field : declaredFields) {
        if (field.isPrivate()) {
          continue;
        }
        String signature = field.toString();
        JField existing = fieldsBySignature.put(signature, field);
        if (existing != null) {
          // TODO(amitmanjhi): Consider whether this is sufficient
          fieldsBySignature.put(signature, existing);
        }
      }
      tempClassType = tempClassType.getSuperclass();
    } while (tempClassType != null);
    return fieldsBySignature.values().toArray(new JField[0]);
  }

  // TODO(amitmanjhi): to optimize, cache results
  private JMethod[] getAccessibleMethods() {
    boolean isInterface = false;
    if (classType.isInterface() != null) {
      isInterface = true;
    }
    Map<String, JMethod> methodsBySignature = new HashMap<String, JMethod>();
    LinkedList<JClassType> classesToBeProcessed = new LinkedList<JClassType>();
    classesToBeProcessed.add(classType);
    JClassType tempClassType = null;
    while (classesToBeProcessed.peek() != null) {
      tempClassType = classesToBeProcessed.remove();
      JMethod declaredMethods[] = tempClassType.getMethods();
      for (JMethod method : declaredMethods) {
        if (method.isPrivate()) {
          continue;
        }
        String signature = ApiAbstractMethod.computeInternalSignature(method);
        JMethod existing = methodsBySignature.put(signature, method);
        if (existing != null) {
          // decide which implementation to keep
          if (existing.getEnclosingType().isAssignableTo(
              method.getEnclosingType())) {
            methodsBySignature.put(signature, existing);
          }
        }
      }
      if (isInterface) {
        classesToBeProcessed.addAll(Arrays.asList(tempClassType.getImplementedInterfaces()));
      } else {
        classesToBeProcessed.add(tempClassType.getSuperclass());
      }
    }
    return methodsBySignature.values().toArray(new JMethod[0]);
  }

  private JAbstractMethod[] getAccessibleMethods(MethodType member) {
    switch (member) {
      case CONSTRUCTOR:
        return classType.getConstructors();
      case METHOD:
        return getAccessibleMethods();
    }
    throw new AssertionError("Unknown value : " + member);
  }

  private void initializeApiConstructorsAndMethods() {
    apiMembersByName = new EnumMap<MethodType, Map<String, Set<ApiAbstractMethod>>>(
        MethodType.class);
    for (MethodType method : MethodType.values()) {
      apiMembersByName.put(method,
          new HashMap<String, Set<ApiAbstractMethod>>());
      Map<String, Set<ApiAbstractMethod>> pointer = apiMembersByName.get(method);
      List<String> notAddedMembers = new ArrayList<String>();
      JAbstractMethod jams[] = getAccessibleMethods(method);
      for (JAbstractMethod jam : jams) {
        if (isApiMember(jam)) {
          String tempName = jam.getName() + jam.getParameters().length;
          Set<ApiAbstractMethod> existingMembers = pointer.get(tempName);
          if (existingMembers == null) {
            existingMembers = new HashSet<ApiAbstractMethod>();
          }
          switch (method) {
            case CONSTRUCTOR:
              existingMembers.add(new ApiConstructor(jam, this));
              break;
            case METHOD:
              existingMembers.add(new ApiMethod(jam, this));
              break;
            default:
              throw new AssertionError("Unknown memberType : " + method);
          }
          pointer.put(tempName, existingMembers);
        } else {
          notAddedMembers.add(jam.toString());
        }
      }
      if (notAddedMembers.size() > 0) {
        logger.log(TreeLogger.SPAM, "class " + getName() + ", removing "
            + notAddedMembers.size() + " nonApi members: " + notAddedMembers,
            null);
      }
    }
  }

  /**
   * Note: Instance members of a class that is not instantiable are not api
   * members.
   */
  private boolean isApiMember(final Object member) {
    boolean isPublic = false;
    boolean isPublicOrProtected = false;
    boolean isStatic = false;

    if (member instanceof JField) {
      JField field = (JField) member;
      isPublic = field.isPublic();
      isPublicOrProtected = isPublic || field.isProtected();
      isStatic = field.isStatic();
    }
    if (member instanceof JAbstractMethod) {
      JAbstractMethod method = (JAbstractMethod) member;
      isPublic = method.isPublic();
      isPublicOrProtected = isPublic || method.isProtected();
      if (method instanceof JMethod) {
        JMethod temp = (JMethod) method;
        isStatic = temp.isStatic();
      } else {
        isStatic = false; // constructors can't be static
      }
    }
    if (ApiCompatibilityChecker.REMOVE_NON_SUBCLASSABLE_ABSTRACT_CLASS_FROM_API) {
      if (!isInstantiableApiClass && !isStatic && !isSubclassableApiClass) {
        return false;
      }
    }
    return (isSubclassableApiClass && isPublicOrProtected)
        || (isNotsubclassableApiClass && isPublic);
  }

}
