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

import com.google.web.bindery.autobean.shared.AutoBean;
import com.google.web.bindery.autobean.shared.AutoBean.PropertyName;
import com.google.web.bindery.autobean.shared.AutoBeanFactory;
import com.google.web.bindery.autobean.vm.impl.BeanMethod;
import com.google.web.bindery.autobean.vm.impl.TypeUtils;
import com.google.web.bindery.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.InstanceRequest;
import com.google.web.bindery.requestfactory.shared.JsonRpcContent;
import com.google.web.bindery.requestfactory.shared.JsonRpcWireName;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.impl.AbstractRequest;
import com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext;
import com.google.web.bindery.requestfactory.shared.impl.RequestData;
import com.google.web.bindery.requestfactory.shared.impl.SimpleProxyId;
import com.google.web.bindery.requestfactory.vm.impl.OperationKey;
import com.google.web.bindery.requestfactory.vm.impl.TypeTokenResolver;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Collection;

/**
 * An in-process implementation of RequestContext.
 */
class InProcessRequestContext extends AbstractRequestContext {
  class RequestContextHandler implements InvocationHandler {
    public InProcessRequestContext getContext() {
      return InProcessRequestContext.this;
    }

    public Object invoke(Object proxy, Method method, final Object[] args) throws Throwable {
      // Maybe delegate to superclass
      Class<?> owner = method.getDeclaringClass();
      if (Object.class.equals(owner) || RequestContext.class.equals(owner)
          || AbstractRequestContext.class.equals(owner)) {
        try {
          return method.invoke(InProcessRequestContext.this, args);
        } catch (InvocationTargetException e) {
          throw e.getCause();
        }
      }

      /*
       * Instance methods treat the 0-th argument as the instance on which to
       * invoke the method.
       */
      final Object[] actualArgs;
      Type returnGenericType;
      boolean isInstance = InstanceRequest.class.isAssignableFrom(method.getReturnType());
      if (isInstance) {
        returnGenericType =
            TypeUtils.getParameterization(InstanceRequest.class, method.getGenericReturnType(),
                method.getReturnType())[1];
        if (args == null) {
          actualArgs = new Object[1];
        } else {
          // Save a slot for the this argument
          actualArgs = new Object[args.length + 1];
          System.arraycopy(args, 0, actualArgs, 1, args.length);
        }
      } else {
        returnGenericType =
            TypeUtils.getSingleParameterization(Request.class, method.getGenericReturnType(),
                method.getReturnType());
        if (args == null) {
          actualArgs = NO_ARGS;
        } else {
          actualArgs = args;
        }
      }

      Class<?> returnType = TypeUtils.ensureBaseType(returnGenericType);
      Class<?> elementType =
          Collection.class.isAssignableFrom(returnType) ? TypeUtils.ensureBaseType(TypeUtils
              .getSingleParameterization(Collection.class, returnGenericType)) : null;

      final RequestData data;
      if (dialect.equals(Dialect.STANDARD)) {
        StringBuilder descriptor = new StringBuilder("(");
        for (Class<?> param : method.getParameterTypes()) {
          descriptor.append(com.google.gwt.dev.asm.Type.getDescriptor(param));
        }
        // Don't care about the return type
        descriptor.append(")V");
        OperationKey operation =
            new OperationKey(context.getName(), method.getName(), descriptor.toString());

        data = new RequestData(operation.get(), actualArgs, returnType, elementType);
      } else {
        // Calculate request metadata
        JsonRpcWireName wireInfo = method.getReturnType().getAnnotation(JsonRpcWireName.class);
        String apiVersion = wireInfo.version();
        String operation = wireInfo.value();

        int foundContent = -1;
        final String[] parameterNames = args == null ? new String[0] : new String[args.length];
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        parameter : for (int i = 0, j = parameterAnnotations.length; i < j; i++) {
          for (Annotation annotation : parameterAnnotations[i]) {
            if (PropertyName.class.equals(annotation.annotationType())) {
              parameterNames[i] = ((PropertyName) annotation).value();
              continue parameter;
            } else if (JsonRpcContent.class.equals(annotation.annotationType())) {
              foundContent = i;
              continue parameter;
            }
          }
          throw new UnsupportedOperationException("No " + PropertyName.class.getCanonicalName()
              + " annotation on parameter " + i + " of method " + method.toString());
        }
        final int contentIdx = foundContent;

        data = new RequestData(operation, actualArgs, returnType, elementType);
        for (int i = 0, j = args.length; i < j; i++) {
          if (i != contentIdx) {
            data.setNamedParameter(parameterNames[i], args[i]);
          } else {
            data.setRequestContent(args[i]);
          }
          data.setApiVersion(apiVersion);
        }
      }

      // Create the request, just filling in the RequestData details
      final AbstractRequest<Object> req =
          new AbstractRequest<Object>(InProcessRequestContext.this) {
            @Override
            protected RequestData makeRequestData() {
              data.setPropertyRefs(propertyRefs);
              return data;
            }
          };

      if (!isInstance) {
        // Instance invocations are enqueued when using() is called
        addInvocation(req);
      }

      if (dialect.equals(Dialect.STANDARD)) {
        return req;
      } else if (dialect.equals(Dialect.JSON_RPC)) {
        // Support optional parameters for JSON-RPC payloads
        Class<?> requestType = method.getReturnType().asSubclass(Request.class);
        return Proxy.newProxyInstance(requestType.getClassLoader(), new Class<?>[] {requestType},
            new InvocationHandler() {
              public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (Object.class.equals(method.getDeclaringClass())
                    || Request.class.equals(method.getDeclaringClass())) {
                  return method.invoke(req, args);
                } else if (BeanMethod.SET.matches(method) || BeanMethod.SET_BUILDER.matches(method)) {
                  req.getRequestData().setNamedParameter(BeanMethod.SET.inferName(method), args[0]);
                  return Void.TYPE.equals(method.getReturnType()) ? null : proxy;
                }
                throw new UnsupportedOperationException(method.toString());
              }
            });
      } else {
        throw new RuntimeException("Should not reach here");
      }
    }
  }

  static final Object[] NO_ARGS = new Object[0];
  private final Class<? extends RequestContext> context;
  private final Dialect dialect;
  private final TypeTokenResolver tokenResolver;

  protected InProcessRequestContext(InProcessRequestFactory factory, Dialect dialect,
      Class<? extends RequestContext> context) {
    super(factory, dialect);
    this.context = context;
    this.tokenResolver = factory.getTypeTokenResolver();
    this.dialect = dialect;
  }

  @Override
  public <T extends RequestContext> T append(T other) {
    RequestContextHandler h = (RequestContextHandler) Proxy.getInvocationHandler(other);
    super.append(h.getContext());
    return other;
  }

  @Override
  protected <T extends BaseProxy> AutoBean<T> createProxy(Class<T> clazz, SimpleProxyId<T> id,
      boolean useAppendedContexts) {
    if (tokenResolver.isReferencedType(clazz.getName())) {
      return super.createProxy(clazz, id, useAppendedContexts);
    }
    throw new IllegalArgumentException("Unknown proxy type " + clazz.getName());
  }

  @Override
  protected AutoBeanFactory getAutoBeanFactory() {
    return ((InProcessRequestFactory) getRequestFactory()).getAutoBeanFactory();
  }
}
