/*
 * 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.thirdparty.guava.common.collect.LinkedHashMultimap;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;
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.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;
  }

  /**
   * 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 && !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 Multimap<String, JMethod> findAllSetters(JClassType fieldType) {
    Multimap<String, JMethod> allSetters = LinkedHashMultimap.create();
    for (JMethod method : fieldType.getInheritableMethods()) {
      if (!isSetterMethod(method)) {
        continue;
      }

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

      // turn "PropertyName" into "propertyName"
      String beanPropertyName = Introspector.decapitalize(propertyName);
      allSetters.put(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)) {
        allSetters.put(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
    Multimap<String, 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;
  }
}
