/*
 * 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.Deobfuscator;
import com.google.web.bindery.requestfactory.vm.impl.OperationKey;

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()) {
          appendDescriptor(descriptor, 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 = parameterNames.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<BaseProxy, Object> req =
          new AbstractRequest<BaseProxy, 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");
      }
    }

    private void appendDescriptor(StringBuilder descriptor, Class<?> param) {
      // Arrays aren't actually used anywhere in RequestFactory, but it's trivial to
      // implement and might be useful later on.
      while (param.isArray()) {
        descriptor.append('[');
        param = param.getComponentType();
      }

      if (param.isPrimitive()) {
        if (param == Boolean.TYPE) {
          descriptor.append('Z');
        } else if (param == Byte.TYPE) {
          descriptor.append('B');
        } else if (param == Character.TYPE) {
          descriptor.append('C');
        } else if (param == Double.TYPE) {
          descriptor.append('D');
        } else if (param == Float.TYPE) {
          descriptor.append('F');
        } else if (param == Integer.TYPE) {
          descriptor.append('I');
        } else if (param == Long.TYPE) {
          descriptor.append('J');
        } else if (param == Short.TYPE) {
          descriptor.append('S');
        } else {
          assert param == Void.TYPE;
          descriptor.append('V');
        }
      } else {
        descriptor.append('L').append(param.getName().replace('.', '/')).append(';');
      }
    }
  }

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

  protected InProcessRequestContext(InProcessRequestFactory factory, Dialect dialect,
      Class<? extends RequestContext> context) {
    super(factory, dialect);
    this.context = context;
    this.deobfuscator = factory.getDeobfuscator();
    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 (deobfuscator.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();
  }
}
