/*
 * Copyright 2010 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.web.bindery.requestfactory.gwt.rebind.model;

import com.google.web.bindery.autobean.gwt.rebind.model.JBeanMethod;
import com.google.web.bindery.autobean.shared.Splittable;
import com.google.gwt.core.ext.TreeLogger;
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.editor.rebind.model.ModelUtils;
import com.google.web.bindery.requestfactory.gwt.rebind.model.EntityProxyModel.Type;
import com.google.web.bindery.requestfactory.gwt.rebind.model.RequestMethod.CollectionType;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.InstanceRequest;
import com.google.web.bindery.requestfactory.shared.JsonRpcProxy;
import com.google.web.bindery.requestfactory.shared.JsonRpcService;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
import com.google.web.bindery.requestfactory.shared.ProxyForName;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.RequestFactory;
import com.google.web.bindery.requestfactory.shared.Service;
import com.google.web.bindery.requestfactory.shared.ServiceName;
import com.google.web.bindery.requestfactory.shared.ValueProxy;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Represents a RequestFactory interface declaration.
 */
public class RequestFactoryModel implements AcceptsModelVisitor {
  public static String poisonedMessage() {
    return "Unable to create RequestFactoryModel model due to previous errors";
  }

  static String badContextReturnType(JMethod method,
      JClassType requestInterface, JClassType instanceRequestInterface) {
    return String.format(
        "Return type %s in method %s must be an interface assignable"
            + " to %s or %s", method.getReturnType(), method.getName(),
        requestInterface.getSimpleSourceName(),
        instanceRequestInterface.getSimpleSourceName());
  }

  static String noSettersAllowed(JMethod found) {
    return String.format("Optional setters not allowed here: ", found.getName());
  }

  private final JClassType collectionInterface;
  private final List<ContextMethod> contextMethods = new ArrayList<ContextMethod>();
  private final JClassType entityProxyInterface;
  private final JClassType factoryType;
  private final JClassType instanceRequestInterface;
  private final JClassType listInterface;
  private final TreeLogger logger;
  private final JClassType mapInterface;
  private final TypeOracle oracle;
  /**
   * This map prevents cyclic type dependencies from overflowing the stack.
   */
  private final Map<JClassType, EntityProxyModel.Builder> peerBuilders = new HashMap<JClassType, EntityProxyModel.Builder>();
  /**
   * Iterated by {@link #getAllProxyModels()}.
   */
  private final Map<JClassType, EntityProxyModel> peers = new LinkedHashMap<JClassType, EntityProxyModel>();
  private boolean poisoned;
  private final JClassType requestContextInterface;
  private final JClassType requestFactoryInterface;
  private final JClassType requestInterface;
  private final JClassType setInterface;
  private final JClassType splittableType;

  private final JClassType valueProxyInterface;

  public RequestFactoryModel(TreeLogger logger, JClassType factoryType)
      throws UnableToCompleteException {
    this.logger = logger;
    this.factoryType = factoryType;
    this.oracle = factoryType.getOracle();
    collectionInterface = oracle.findType(Collection.class.getCanonicalName());
    entityProxyInterface = oracle.findType(EntityProxy.class.getCanonicalName());
    instanceRequestInterface = oracle.findType(InstanceRequest.class.getCanonicalName());
    listInterface = oracle.findType(List.class.getCanonicalName());
    mapInterface = oracle.findType(Map.class.getCanonicalName());
    requestContextInterface = oracle.findType(RequestContext.class.getCanonicalName());
    requestFactoryInterface = oracle.findType(RequestFactory.class.getCanonicalName());
    requestInterface = oracle.findType(Request.class.getCanonicalName());
    setInterface = oracle.findType(Set.class.getCanonicalName());
    splittableType = oracle.findType(Splittable.class.getCanonicalName());
    valueProxyInterface = oracle.findType(ValueProxy.class.getCanonicalName());

    for (JMethod method : factoryType.getOverridableMethods()) {
      if (method.getEnclosingType().equals(requestFactoryInterface)) {
        // Ignore methods defined an RequestFactory itself
        continue;
      }

      if (method.getParameters().length > 0) {
        poison("Unexpected parameter on method %s", method.getName());
        continue;
      }

      JClassType contextType = method.getReturnType().isInterface();
      if (contextType == null
          || !requestContextInterface.isAssignableFrom(contextType)) {
        poison("Unexpected return type %s on method %s is not"
            + " an interface assignable to %s",
            method.getReturnType().getQualifiedSourceName(), method.getName(),
            requestContextInterface.getSimpleSourceName());
        continue;
      }

      ContextMethod.Builder builder = new ContextMethod.Builder();
      builder.setDeclaredMethod(method);
      buildContextMethod(builder, contextType);
      contextMethods.add(builder.build());
    }

    if (poisoned) {
      die(poisonedMessage());
    }
  }

  public void accept(ModelVisitor visitor) {
    if (visitor.visit(this)) {
      for (EntityProxyModel model : getAllProxyModels()) {
        model.accept(visitor);
      }
      for (ContextMethod method : getMethods()) {
        method.accept(visitor);
      }
    }
    visitor.endVisit(this);
  }

  public Collection<EntityProxyModel> getAllProxyModels() {
    return Collections.unmodifiableCollection(peers.values());
  }

  public JClassType getFactoryType() {
    return factoryType;
  }

  public List<ContextMethod> getMethods() {
    return Collections.unmodifiableList(contextMethods);
  }

  public EntityProxyModel getPeer(JClassType entityProxyType) {
    return peers.get(entityProxyType);
  }

  /**
   * For debugging use only.
   */
  @Override
  public String toString() {
    return getFactoryType().getQualifiedSourceName();
  }

  /**
   * Examine a RequestContext subtype to populate a ContextMethod.
   */
  private void buildContextMethod(ContextMethod.Builder contextBuilder,
      JClassType contextType) throws UnableToCompleteException {
    Service serviceAnnotation = contextType.getAnnotation(Service.class);
    ServiceName serviceNameAnnotation = contextType.getAnnotation(ServiceName.class);
    JsonRpcService jsonRpcAnnotation = contextType.getAnnotation(JsonRpcService.class);
    if (serviceAnnotation == null && serviceNameAnnotation == null
        && jsonRpcAnnotation == null) {
      poison("RequestContext subtype %s is missing a @%s or @%s annotation",
          contextType.getQualifiedSourceName(), Service.class.getSimpleName(),
          JsonRpcService.class.getSimpleName());
      return;
    }

    List<RequestMethod> requestMethods = new ArrayList<RequestMethod>();
    for (JMethod method : contextType.getInheritableMethods()) {
      if (method.getEnclosingType().equals(requestContextInterface)) {
        // Ignore methods declared in RequestContext
        continue;
      }

      RequestMethod.Builder methodBuilder = new RequestMethod.Builder();
      methodBuilder.setDeclarationMethod(method);

      if (!validateContextMethodAndSetDataType(methodBuilder, method,
          jsonRpcAnnotation != null)) {
        continue;
      }

      requestMethods.add(methodBuilder.build());
    }

    contextBuilder.setRequestMethods(requestMethods);
  }

  private void die(String message) throws UnableToCompleteException {
    poison(message);
    throw new UnableToCompleteException();
  }

  private EntityProxyModel getEntityProxyType(JClassType entityProxyType)
      throws UnableToCompleteException {
    entityProxyType = ModelUtils.ensureBaseType(entityProxyType);
    EntityProxyModel toReturn = peers.get(entityProxyType);
    if (toReturn == null) {
      EntityProxyModel.Builder inProgress = peerBuilders.get(entityProxyType);
      if (inProgress != null) {
        toReturn = inProgress.peek();
      }
    }
    if (toReturn == null) {
      EntityProxyModel.Builder builder = new EntityProxyModel.Builder();
      peerBuilders.put(entityProxyType, builder);

      builder.setQualifiedBinaryName(ModelUtils.getQualifiedBaseBinaryName(entityProxyType));
      builder.setQualifiedSourceName(ModelUtils.getQualifiedBaseSourceName(entityProxyType));
      if (entityProxyInterface.isAssignableFrom(entityProxyType)) {
        builder.setType(Type.ENTITY);
      } else if (valueProxyInterface.isAssignableFrom(entityProxyType)) {
        builder.setType(Type.VALUE);
      } else {
        poison("The type %s is not assignable to either %s or %s",
            entityProxyInterface.getQualifiedSourceName(),
            valueProxyInterface.getQualifiedSourceName());
        // Cannot continue, since knowing the behavior is crucial
        die(poisonedMessage());
      }

      // Get the server domain object type
      ProxyFor proxyFor = entityProxyType.getAnnotation(ProxyFor.class);
      ProxyForName proxyForName = entityProxyType.getAnnotation(ProxyForName.class);
      JsonRpcProxy jsonRpcProxy = entityProxyType.getAnnotation(JsonRpcProxy.class);
      if (proxyFor == null && proxyForName == null && jsonRpcProxy == null) {
        poison("The %s type does not have a @%s, @%s, or @%s annotation",
            entityProxyType.getQualifiedSourceName(),
            ProxyFor.class.getSimpleName(), ProxyForName.class.getSimpleName(),
            JsonRpcProxy.class.getSimpleName());
      }

      // Look at the methods declared on the EntityProxy
      List<RequestMethod> requestMethods = new ArrayList<RequestMethod>();
      Map<String, JMethod> duplicatePropertyGetters = new HashMap<String, JMethod>();
      for (JMethod method : entityProxyType.getInheritableMethods()) {
        if (method.getEnclosingType().equals(entityProxyInterface)) {
          // Ignore methods on EntityProxy
          continue;
        }
        RequestMethod.Builder methodBuilder = new RequestMethod.Builder();
        methodBuilder.setDeclarationMethod(method);

        JType transportedType;
        String name = method.getName();
        if (JBeanMethod.GET.matches(method)) {
          transportedType = method.getReturnType();
          String propertyName = JBeanMethod.GET.inferName(method);
          JMethod previouslySeen = duplicatePropertyGetters.get(propertyName);
          if (previouslySeen == null) {
            duplicatePropertyGetters.put(propertyName, method);
          } else {
            poison("Duplicate accessors for property %s: %s() and %s()",
                propertyName, previouslySeen.getName(), method.getName());
          }

        } else if (JBeanMethod.SET.matches(method)
            || JBeanMethod.SET_BUILDER.matches(method)) {
          transportedType = method.getParameters()[0].getType();

        } else if (name.equals("stableId")
            && method.getParameters().length == 0) {
          // Ignore any overload of stableId
          continue;
        } else {
          poison("The method %s is neither a getter nor a setter",
              method.getReadableDeclaration());
          continue;
        }
        validateTransportableType(methodBuilder, transportedType, false);
        RequestMethod requestMethod = methodBuilder.build();
        requestMethods.add(requestMethod);
      }
      builder.setRequestMethods(requestMethods);

      toReturn = builder.build();
      peers.put(entityProxyType, toReturn);
      peerBuilders.remove(entityProxyType);
    }
    return toReturn;
  }

  private void poison(String message, Object... args) {
    logger.log(TreeLogger.ERROR, String.format(message, args));
    poisoned = true;
  }

  /**
   * Examine a RequestContext method to see if it returns a transportable type.
   */
  private boolean validateContextMethodAndSetDataType(
      RequestMethod.Builder methodBuilder, JMethod method, boolean allowSetters)
      throws UnableToCompleteException {
    JClassType requestReturnType = method.getReturnType().isInterface();
    JClassType invocationReturnType;
    if (requestReturnType == null) {
      // Primitive return type
      poison(badContextReturnType(method, requestInterface,
          instanceRequestInterface));
      return false;
    }

    if (instanceRequestInterface.isAssignableFrom(requestReturnType)) {
      // Instance method invocation
      JClassType[] params = ModelUtils.findParameterizationOf(
          instanceRequestInterface, requestReturnType);
      methodBuilder.setInstanceType(getEntityProxyType(params[0]));
      invocationReturnType = params[1];
    } else if (requestInterface.isAssignableFrom(requestReturnType)) {
      // Static method invocation
      JClassType[] params = ModelUtils.findParameterizationOf(requestInterface,
          requestReturnType);
      invocationReturnType = params[0];

    } else {
      // Unhandled return type, must be something random
      poison(badContextReturnType(method, requestInterface,
          instanceRequestInterface));
      return false;
    }

    // Validate the parameters
    boolean paramsOk = true;
    JParameter[] params = method.getParameters();
    for (int i = 0; i < params.length; ++i) {
      JParameter param = params[i];
      paramsOk = validateTransportableType(new RequestMethod.Builder(),
          param.getType(), false)
          && paramsOk;
    }

    // Validate any extra properties on the request type
    for (JMethod maybeSetter : requestReturnType.getInheritableMethods()) {
      if (JBeanMethod.SET.matches(maybeSetter)
          || JBeanMethod.SET_BUILDER.matches(maybeSetter)) {
        if (allowSetters) {
          methodBuilder.addExtraSetter(maybeSetter);
        } else {
          poison(noSettersAllowed(maybeSetter));
        }
      }
    }
    return validateTransportableType(methodBuilder, invocationReturnType, true);
  }

  /**
   * Examines a type to see if it can be transported.
   */
  private boolean validateTransportableType(
      RequestMethod.Builder methodBuilder, JType type, boolean requireObject)
      throws UnableToCompleteException {
    JClassType transportedClass = type.isClassOrInterface();
    if (transportedClass == null) {
      if (requireObject) {
        poison("The type %s cannot be transported by RequestFactory as"
            + " a return type", type.getQualifiedSourceName());
        return false;
      } else {
        // Primitives always ok
        return true;
      }
    }

    if (ModelUtils.isValueType(oracle, transportedClass)
        || splittableType.equals(transportedClass)) {
      // Simple values, like Integer and String
      methodBuilder.setValueType(true);
    } else if (entityProxyInterface.isAssignableFrom(transportedClass)
        || valueProxyInterface.isAssignableFrom(transportedClass)) {
      // EntityProxy and ValueProxy return types
      methodBuilder.setEntityType(getEntityProxyType(transportedClass));
    } else if (collectionInterface.isAssignableFrom(transportedClass)) {
      // Only allow certain collections for now
      JParameterizedType parameterized = transportedClass.isParameterized();
      if (parameterized == null) {
        poison("Requests that return collections of List or Set must be parameterized");
        return false;
      }
      if (listInterface.equals(parameterized.getBaseType())) {
        methodBuilder.setCollectionType(CollectionType.LIST);
      } else if (setInterface.equals(parameterized.getBaseType())) {
        methodBuilder.setCollectionType(CollectionType.SET);
      } else {
        poison("Requests that return collections may be declared with"
            + " %s or %s only", listInterface.getQualifiedSourceName(),
            setInterface.getQualifiedSourceName());
        return false;
      }
      // Also record the element type in the method builder
      JClassType elementType = ModelUtils.findParameterizationOf(
          collectionInterface, transportedClass)[0];
      methodBuilder.setCollectionElementType(elementType);
      validateTransportableType(methodBuilder, elementType, requireObject);
    } else if (mapInterface.isAssignableFrom(transportedClass)) {
      JParameterizedType parameterized = transportedClass.isParameterized();
      if (parameterized == null) {
        poison("Requests that return Maps must be parameterized");
        return false;
      }
      if (mapInterface.equals(parameterized.getBaseType())) {
        methodBuilder.setCollectionType(CollectionType.MAP);
      } else {
        poison("Requests that return maps may be declared with" + " %s only",
            mapInterface.getQualifiedSourceName());
        return false;
      }
      // Also record the element type in the method builder
      JClassType[] params = ModelUtils.findParameterizationOf(mapInterface,
          transportedClass);
      JClassType keyType = params[0];
      JClassType valueType = params[1];
      methodBuilder.setMapKeyType(keyType);
      methodBuilder.setMapValueType(valueType);
      validateTransportableType(methodBuilder, keyType, requireObject);
      validateTransportableType(methodBuilder, valueType, requireObject);
    } else {
      // Unknown type, fail
      poison("Invalid Request parameterization %s",
          transportedClass.getQualifiedSourceName());
      return false;
    }
    methodBuilder.setDataType(transportedClass);
    return true;
  }

}
