/*
 * 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;

import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.rebind.model.OwnerClass;

/**
 * This class implements an easy way to bind widget event handlers to methods
 * annotated with {@link com.google.gwt.uibinder.client.UiHandler} so that the
 * user doesn't need to worry about writing code to implement these bindings.
 *
 * <p>
 * For instance, the class defined below:
 *
 * <pre>
 *   public class MyClass {
 *     @UiField Label label;
 *
 *     @UiBinder({"label", "link"})
 *     public void doClick(ClickEvent e) {
 *       // do something
 *     }
 *   }
 * </pre>
 *
 * will generate a piece of code like:
 *
 * <pre>
 *    ClickHandler handler0 = new ClickHandler() {
 *      @Override
 *      public void onClick(ClickEvent event) {
 *        owner.doClick(event);
 *      }
 *   });
 *   label.addClickHandler(handler0);
 *   link.addClickHandler(handler0);
 * </pre>
 *
 * Notice that the <b>link</b> object doesn't need to be annotated with
 * {@link com.google.gwt.uibinder.client.UiField} as long as it exists
 * (annotated with ui:field) in the template.
 */
class HandlerEvaluator {

  private static final String HANDLER_BASE_NAME = "handlerMethodWithNameVeryUnlikelyToCollideWithUserFieldNames";
  /*
   * TODO(rjrjr) The correct fix is to put the handlers in a locally defined
   * class, making the generated code look like this
   *
   * http://docs.google.com/Doc?docid=0AQfnKgX9tAdgZGZ2cTM5YjdfMmQ4OTk0eGhz&hl=en
   *
   * But that needs to wait for a refactor to get most of this stuff out of here
   * and into com.google.gwt.uibinder.rebind.model
   */
  private int varCounter = 0;

  private final MortalLogger logger;

  private final JClassType handlerRegistrationJClass;
  private final JClassType eventHandlerJClass;
  private final OwnerClass ownerClass;

  /**
   * The verbose testable constructor.
   *
   * @param ownerClass a descriptor of the UI owner class
   * @param logger the logger for warnings and errors
   * @param oracle the type oracle
   */
  HandlerEvaluator(OwnerClass ownerClass, MortalLogger logger, TypeOracle oracle) {
    this.ownerClass = ownerClass;
    this.logger = logger;

    handlerRegistrationJClass = oracle.findType(HandlerRegistration.class.getName());
    eventHandlerJClass = oracle.findType(EventHandler.class.getName());
  }

  /**
   * Runs the evaluator in the given class according to the valid fields
   * extracted from the template (via attribute ui:field).
   *
   * @param writer the writer used to output the results
   * @param fieldManager the field manager instance
   * @param uiOwner the name of the class evaluated here that owns the template
   */
  public void run(IndentedWriter writer, FieldManager fieldManager,
      String uiOwner) throws UnableToCompleteException {

    // Iterate through all methods defined in the class.
    for (JMethod method : ownerClass.getUiHandlers()) {
      // Evaluate the method.
      String boundMethod = method.getName();
      if (method.isPrivate()) {
        logger.die("Method '%s' cannot be private.", boundMethod);
      }

      // Retrieves both event and handler types.
      JParameter[] parameters = method.getParameters();
      if (parameters.length != 1) {
        logger.die("Method '%s' must have a single event parameter defined.",
            boundMethod);
      }
      JClassType eventType = parameters[0].getType().isClass();

      JClassType handlerType = getHandlerForEvent(eventType);
      if (handlerType == null) {
        logger.die("Parameter '%s' is not an event (subclass of GwtEvent).",
            eventType.getName());
      }

      // Cool to add the handler in the output.
      String handlerVarName = HANDLER_BASE_NAME + (++varCounter);
      writeHandler(writer, uiOwner, handlerVarName, handlerType, eventType,
          boundMethod);

      // Adds the handler created above.
      UiHandler annotation = method.getAnnotation(UiHandler.class);
      for (String objectName : annotation.value()) {
        // Is the field object valid?
        FieldWriter fieldWriter = fieldManager.lookup(objectName);
        if (fieldWriter == null) {
          logger.die(
              ("Method '%s' can not be bound. You probably missed ui:field='%s' "
                  + "in the template."), boundMethod, objectName);
        }

        // Retrieves the "add handler" method in the object.
        JMethod addHandlerMethodType = getAddHandlerMethodForObject(
            fieldWriter.getType(), handlerType);
        if (addHandlerMethodType == null) {
          logger.die("Field '%s' does not have an 'add%s' method associated.",
              objectName, handlerType.getName());
        }

        // Cool to tie the handler into the object.
        writeAddHandler(writer, handlerVarName, addHandlerMethodType.getName(),
            objectName);
      }
    }
  }

  /**
   * Writes a handler entry using the given writer.
   *
   * @param writer the writer used to output the results
   * @param uiOwner the name of the class evaluated here that owns the template
   * @param handlerVarName the name of the handler variable
   * @param handlerType the handler we want to create
   * @param eventType the event associated with the handler
   * @param boundMethod the method bound in the handler
   */
  protected void writeHandler(IndentedWriter writer, String uiOwner,
      String handlerVarName, JClassType handlerType, JClassType eventType,
      String boundMethod) throws UnableToCompleteException {

    // Retrieves the single method (usually 'onSomething') related to all
    // handlers. Ex: onClick in ClickHandler, onBlur in BlurHandler ...
    JMethod[] methods = handlerType.getMethods();
    if (methods.length != 1) {
      logger.die("'%s' has more than one method defined.",
          handlerType.getName());
    }

    // Checks if the method has an Event as parameter. Ex: ClickEvent in
    // onClick, BlurEvent in onBlur ...
    JParameter[] parameters = methods[0].getParameters();
    if (parameters.length != 1 || parameters[0].getType() != eventType) {
      logger.die("Method '%s' needs '%s' as parameter", methods[0].getName(),
          eventType.getName());
    }

    writer.newline();
    writer.write("final %1$s %2$s = new %1$s() {",
        handlerType.getParameterizedQualifiedSourceName(), handlerVarName);
    writer.indent();
    writer.write("public void %1$s(%2$s event) {", methods[0].getName(),
        eventType.getParameterizedQualifiedSourceName());
    writer.indent();
    writer.write("%1$s.%2$s(event);", uiOwner, boundMethod);
    writer.outdent();
    writer.write("}");
    writer.outdent();
    writer.write("};");
  }

  /**
   * Adds the created handler to the given object (field).
   *
   * @param writer the writer used to output the results
   * @param handlerVarName the name of the handler variable
   * @param addHandlerMethodName the "add handler" method name associated with
   *          the object
   * @param objectName the name of the object we want to tie the handler
   */
  void writeAddHandler(IndentedWriter writer, String handlerVarName,
      String addHandlerMethodName, String objectName) {
    writer.write("%1$s.%2$s(%3$s);", objectName, addHandlerMethodName,
        handlerVarName);
  }

  /**
   * Checks if a specific handler is valid for a given object and return the
   * method that ties them. The object must override a method that returns
   * {@link com.google.gwt.event.shared.HandlerRegistration} and receives a
   * single input parameter of the same type of handlerType.
   *
   * <p>
   * Output an error in case more than one method match the conditions described
   * above.
   * </p>
   *
   * <pre>
   *   <b>Examples:</b>
   *    - HandlerRegistration addClickHandler(ClickHandler handler)
   *    - HandlerRegistration addMouseOverHandler(MouseOverHandler handler)
   *    - HandlerRegistration addSubmitCompleteHandler(
   *          FormPanel.SubmitCompleteHandler handler)
   * </pre>
   *
   * @param objectType the object type we want to check
   * @param handlerType the handler type we want to check in the object
   *
   * @return the method that adds handlerType into objectType, or <b>null</b> if
   *         no method was found
   */
  private JMethod getAddHandlerMethodForObject(JClassType objectType,
      JClassType handlerType) throws UnableToCompleteException {
    JMethod handlerMethod = null;
    for (JMethod method : objectType.getOverridableMethods()) {

      // Condition 1: returns HandlerRegistration?
      if (method.getReturnType() == handlerRegistrationJClass) {

        // Condition 2: single parameter of the same type of handlerType?
        JParameter[] parameters = method.getParameters();
        if ((parameters.length == 1)
            && handlerType.equals(parameters[0].getType())) {

          // Condition 3: does more than one method match the condition?
          if (handlerMethod != null) {
            logger.die(
                ("This handler cannot be generated. Methods '%s' and '%s' are "
                    + "ambiguous. Which one to pick?"), method, handlerMethod);
          }

          handlerMethod = method;
        }
      }
    }
    return handlerMethod;
  }

  /**
   * Retrieves the handler associated with the event.
   *
   * @param eventType the given event
   * @return the associated handler, <code>null</code> if not found
   */
  private JClassType getHandlerForEvent(JClassType eventType) {

    // All handlers event must have an overrided method getAssociatedType().
    // We take advantage of this information to get the associated handler.
    // Ex:
    // com.google.gwt.event.dom.client.ClickEvent
    // ---> com.google.gwt.event.dom.client.ClickHandler
    //
    // com.google.gwt.event.dom.client.BlurEvent
    // ---> com.google.gwt.event.dom.client.BlurHandler

    if (eventType == null) {
      return null;
    }

    JMethod method = eventType.findMethod("getAssociatedType", new JType[0]);
    if (method == null) {
      logger.warn(
          "Method 'getAssociatedType()' could not be found in the event '%s'.",
          eventType.getName());
      return null;
    }

    JType returnType = method.getReturnType();
    if (returnType == null) {
      logger.warn(
          "The method 'getAssociatedType()' in the event '%s' returns void.",
          eventType.getName());
      return null;
    }

    JParameterizedType isParameterized = returnType.isParameterized();
    if (isParameterized == null) {
      logger.warn(
          "The method 'getAssociatedType()' in '%s' does not return Type<? extends EventHandler>.",
          eventType.getName());
      return null;
    }

    JClassType[] argTypes = isParameterized.getTypeArgs();
    if ((argTypes.length != 1)
        && !argTypes[0].isAssignableTo(eventHandlerJClass)) {
      logger.warn(
          "The method 'getAssociatedType()' in '%s' does not return Type<? extends EventHandler>.",
          eventType.getName());
      return null;
    }

    return argTypes[0];
  }
}
