/*
 * Copyright 2009 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.uibinder.rebind.model;

import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JConstructor;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.shared.impl.StringCase;
import com.google.gwt.dev.util.Pair;
import com.google.gwt.uibinder.client.UiChild;
import com.google.gwt.uibinder.client.UiConstructor;
import com.google.gwt.uibinder.rebind.MortalLogger;
import com.google.gwt.uibinder.rebind.UiBinderContext;

import java.beans.Introspector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Descriptor for a class which can be used as a @UiField. This is usually a
 * widget, but can also be a resource (such as Messages or an ImageBundle). Also
 * notice that the existence of an OwnerFieldClass doesn't mean the class is
 * actually present as a field in the owner.
 */
public class OwnerFieldClass {
  
  private static final int DEFAULT_COST = 4;
  private static final Map<String, Integer> TYPE_RANK;
  static {
    HashMap<String, Integer> tmpTypeRank = new HashMap<String, Integer>();
    tmpTypeRank.put("java.lang.String", 1);
    tmpTypeRank.put("boolean", 2);
    tmpTypeRank.put("byte", 2);
    tmpTypeRank.put("char", 2);
    tmpTypeRank.put("double", 2);
    tmpTypeRank.put("float", 2);
    tmpTypeRank.put("int", 2);
    tmpTypeRank.put("long", 2);
    tmpTypeRank.put("short", 2);
    tmpTypeRank.put("java.lang.Boolean", 3);
    tmpTypeRank.put("java.lang.Byte", 3);
    tmpTypeRank.put("java.lang.Character", 3);
    tmpTypeRank.put("java.lang.Double", 3);
    tmpTypeRank.put("java.lang.Float", 3);
    tmpTypeRank.put("java.lang.Integer", 3);
    tmpTypeRank.put("java.lang.Long", 3);
    tmpTypeRank.put("java.lang.Short", 3);
    TYPE_RANK = Collections.unmodifiableMap(tmpTypeRank);
  }
  
  /**
   * Gets or creates the descriptor for the given field class.
   *
   * @param forType the field type to get a descriptor for
   * @param logger TODO
   * @param context 
   * @return the descriptor
   */
  public static OwnerFieldClass getFieldClass(JClassType forType,
      MortalLogger logger, UiBinderContext context)
      throws UnableToCompleteException {
    OwnerFieldClass clazz = context.getOwnerFieldClass(forType);
    if (clazz == null) {
      clazz = new OwnerFieldClass(forType, logger);
      context.putOwnerFieldClass(forType, clazz);
    }
    return clazz;
  }

  private Set<String> ambiguousSetters;
  private final MortalLogger logger;
  private final JClassType rawType;
  private final Map<String, JMethod> setters = new HashMap<String, JMethod>();
  /**
   * Mapping from all of the @UiChild tags to their corresponding methods and
   * limits on being called.
   */
  private final Map<String, Pair<JMethod, Integer>> uiChildren = new HashMap<String, Pair<JMethod, Integer>>();

  private JConstructor uiConstructor;
 
  /**
   * Default constructor. This is package-visible for testing only.
   *
   * @param forType the type of the field class
   * @param logger
   * @throws UnableToCompleteException if the class is not valid
   */
  OwnerFieldClass(JClassType forType, MortalLogger logger)
      throws UnableToCompleteException {
    this.rawType = forType;
    this.logger = logger;

    findUiConstructor(forType);
    findSetters(forType);
    findUiChildren(forType);
  }

  /**
   * Returns the field's raw type.
   */
  public JClassType getRawType() {
    return rawType;
  }

  /**
   * Finds the setter method for a given property.
   *
   * @param propertyName the name of the property
   * @return the setter method, or null if none exists
   */
  public JMethod getSetter(String propertyName)
      throws UnableToCompleteException {
   
    if (ambiguousSetters != null && ambiguousSetters.contains(propertyName)) {
      logger.die("Ambiguous setter requested: " + rawType.getName() + "."
          + propertyName);
    }

    return setters.get(propertyName);
  }

  /**
   * Returns a list of methods annotated with @UiChild.
   * 
   * @return a list of all add child methods
   */
  public Map<String, Pair<JMethod, Integer>> getUiChildMethods() {
    return uiChildren;
  }

  /**
   * Returns the constructor annotated with @UiConstructor, or null if none
   * exists.
   */
  public JConstructor getUiConstructor() {
    return uiConstructor;
  }

  /**
   * Adds a setter for a given property to the given map of setters.
   *
   * @param allSetters the map of setters (keyed by property name)
   * @param propertyName the property name to use
   * @param method the setter to use
   */
  private void addSetter(Map<String, Collection<JMethod>> allSetters,
      String propertyName, JMethod method) {
    Collection<JMethod> propertyMethods = allSetters.get(propertyName);
    if (propertyMethods == null) {
      propertyMethods = new ArrayList<JMethod>();
      allSetters.put(propertyName, propertyMethods);
    }

    propertyMethods.add(method);
  }

  /**
   * Given a collection of setters for the same property, picks which one to
   * use. Not having a proper setter is not an error unless of course the user
   * tries to use it.
   *
   * @param propertyName the name of the property/setter.
   * @param propertySetters the collection of setters.
   * @return the setter to use, or null if none is good enough.
   */
  private JMethod disambiguateSetters(String propertyName, 
      Collection<JMethod> propertySetters) {
    
    // if only have one overload, there is no need to rank them.
    if (propertySetters.size() == 1) {
      return propertySetters.iterator().next();
    }
    
    // rank overloads and pick the one with minimum 'cost' of conversion.
    JMethod preferredMethod = null;
    int minRank = Integer.MAX_VALUE;
    for (JMethod method : propertySetters) {
      int rank = rankMethodOnParameters(method);
      if (rank < minRank) {
        minRank = rank;
        preferredMethod = method;
        ambiguousSetters.remove(propertyName);
      } else if (rank == minRank && 
          !sameParameterTypes(preferredMethod, method)) {
        // sameParameterTypes test is necessary because a setter can be 
        // overridden by a subclass and that is not considered ambiguous. 
        if (!ambiguousSetters.contains(propertyName)) {
          ambiguousSetters.add(propertyName);
        }
      }
    }
    
    // if the setter is ambiguous, return null.
    if (ambiguousSetters.contains(propertyName)) {
      return null;
    }
    
    // the setter is not ambiguous therefore return the preferred overload.
    return preferredMethod;
  }

  /**
   * Recursively finds all setters for the given class and its superclasses.
   *
   * @param fieldType the leaf type to look at
   * @return a multimap of property name to the setter methods
   */
  private Map<String, Collection<JMethod>> findAllSetters(JClassType fieldType) {
    Map<String, Collection<JMethod>> allSetters;

    // First, get all setters from the parent class, recursively.
    JClassType superClass = fieldType.getSuperclass();
    if (superClass != null) {
      allSetters = findAllSetters(superClass);
    } else {
      // Stop recursion - deepest level creates return value
      allSetters = new HashMap<String, Collection<JMethod>>();
    }

    JMethod[] methods = fieldType.getMethods();
    for (JMethod method : methods) {
      if (!isSetterMethod(method)) {
        continue;
      }

      // Take out "set"
      String propertyName = method.getName().substring(3);

      // turn "PropertyName" into "propertyName"
      String beanPropertyName = Introspector.decapitalize(propertyName);
      addSetter(allSetters, beanPropertyName, method);

      // keep backwards compatibility (i.e. hTML instead of HTML for setHTML)
      String legacyPropertyName = StringCase.toLower(propertyName.substring(0, 1))
          + propertyName.substring(1);
      if (!legacyPropertyName.equals(beanPropertyName)) {
        addSetter(allSetters, legacyPropertyName, method);
      }
    }

    return allSetters;
  }

  /**
   * Finds all setters in the class, and puts them in the {@link #setters}
   * field.
   *
   * @param fieldType the type of the field
   */
  private void findSetters(JClassType fieldType) {
    // Pass one - get all setter methods
    Map<String, Collection<JMethod>> allSetters = findAllSetters(fieldType);

    // Pass two - disambiguate
    ambiguousSetters = new HashSet<String>();
    for (String propertyName : allSetters.keySet()) {
      Collection<JMethod> propertySetters = allSetters.get(propertyName);
      JMethod setter = disambiguateSetters(propertyName, propertySetters);
      setters.put(propertyName, setter);
    }
    
    if (ambiguousSetters.size() == 0) {
      ambiguousSetters = null;
    }
  }

  /**
   * Scans the class to find all methods annotated with @UiChild.
   *
   * @param ownerType the type of the owner class
   * @throws UnableToCompleteException
   */
  private void findUiChildren(JClassType ownerType)
      throws UnableToCompleteException {
    while (ownerType != null) {
      JMethod[] methods = ownerType.getMethods();
      for (JMethod method : methods) {
        UiChild annotation = method.getAnnotation(UiChild.class);
        if (annotation != null) {
          String tag = annotation.tagname();
          int limit = annotation.limit();
          if (tag.equals("")) {
            String name = method.getName();
            if (name.startsWith("add")) {
              tag = StringCase.toLower(name.substring(3));
            } else {
              logger.die(method.getName()
                  + " must either specify a UiChild tagname or begin "
                  + "with \"add\".");
            }
          }
          JParameter[] parameters = method.getParameters();
          if (parameters.length == 0) {
            logger.die("%s must take at least one Object argument", method.getName());
          }
          JType type = parameters[0].getType();
          if (type.isClassOrInterface() == null) {
            logger.die("%s first parameter must be an object type, found %s", 
                method.getName(), type.getQualifiedSourceName());
          }
          uiChildren.put(tag, Pair.create(method, limit));
        }
      }
      ownerType = ownerType.getSuperclass();
    }
  }

  /**
   * Finds the constructor annotated with @UiConcontructor if there is one, and
   * puts it in the {@link #uiConstructor} field.
   *
   * @param fieldType the type of the field
   */
  private void findUiConstructor(JClassType fieldType)
      throws UnableToCompleteException {
    for (JConstructor ctor : fieldType.getConstructors()) {
      if (ctor.getAnnotation(UiConstructor.class) != null) {
        if (uiConstructor != null) {
          logger.die(fieldType.getName()
              + " has more than one constructor annotated with @UiConstructor");
        }
        uiConstructor = ctor;
      }
    }
  }

  /**
   * Checks whether the given method qualifies as a setter. This looks at the
   * method qualifiers, name and return type, but not at the parameter types.
   *
   * @param method the method to look at
   * @return whether it's a setter
   */
  private boolean isSetterMethod(JMethod method) {
    // All setter methods should be public void setSomething(...)
    return method.isPublic() && !method.isStatic()
        && method.getName().startsWith("set") && method.getName().length() > 3
        && method.getReturnType() == JPrimitiveType.VOID;
  }
  
  /**
   * Ranks given method based on parameter conversion cost. A lower rank is
   * preferred over a higher rank since it has a lower cost of conversion.
   * 
   * The ranking criteria is as follows:
   * 1) methods with fewer arguments are preferred. for instance:
   *    'setValue(int)' is preferred 'setValue(int, int)'.
   * 2) within a set of overloads with the same number of arguments:
   * 2.1) String has the lowest cost = 1
   * 2.2) primitive types, cost = 2
   * 2.3) boxed primitive types, cost = 3
   * 2.4) any (reference types, etc), cost = 4.
   * 3) if a setter is overridden by a subclass and have the exact same argument
   * types, it will not be considered ambiguous. 
   *  
   * The cost mapping is defined in 
   * {@link #TYPE_RANK typeRank }
   * @param method
   * @return the rank of the method.
   */
  private int rankMethodOnParameters(JMethod method) {
    JParameter[] params = method.getParameters();
    int rank = 0;
    for (int i = 0; i < Math.min(params.length, 10); i++) {
      JType paramType = params[i].getType();
      int cost = DEFAULT_COST;
      if (TYPE_RANK.containsKey(paramType.getQualifiedSourceName())) {
        cost = TYPE_RANK.get(paramType.getQualifiedSourceName());
      }
      assert (cost >= 0 && cost <= 0x07);
      rank = rank | (cost << (3 * i));
    }
    assert (rank >= 0);
    return rank;
  }
  
  /**
   * Checks whether two methods have the same parameter types.
   *
   * @param m1 the first method to compare
   * @param m2 the second method to compare
   * @return whether the methods have the same parameter types
   */
  private boolean sameParameterTypes(JMethod m1, JMethod m2) {
    JParameter[] p1 = m1.getParameters();
    JParameter[] p2 = m2.getParameters();

    if (p1.length != p2.length) {
      return false;
    }

    for (int i = 0; i < p1.length; i++) {
      JType type1 = p1[i].getType();
      JType type2 = p2[i].getType();

      if (!type1.equals(type2)) {
        return false;
      }
    }

    return true;
  }
}
