/*
 * 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.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.Locale;
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 = propertyName.substring(0, 1).toLowerCase(Locale.ROOT)
          + 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 = name.substring(3).toLowerCase(Locale.ROOT);
            } 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;
  }
}
