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

import com.google.gwt.user.server.Base64Utils;
import com.google.web.bindery.autobean.shared.AutoBean;
import com.google.web.bindery.autobean.shared.AutoBeanCodex;
import com.google.web.bindery.autobean.shared.AutoBeanUtils;
import com.google.web.bindery.autobean.shared.AutoBeanVisitor;
import com.google.web.bindery.autobean.shared.Splittable;
import com.google.web.bindery.autobean.shared.ValueCodex;
import com.google.web.bindery.autobean.vm.AutoBeanFactorySource;
import com.google.web.bindery.autobean.vm.Configuration;
import com.google.web.bindery.autobean.vm.impl.TypeUtils;
import com.google.web.bindery.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxyId;
import com.google.web.bindery.requestfactory.shared.InstanceRequest;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.ServerFailure;
import com.google.web.bindery.requestfactory.shared.WriteOperation;
import com.google.web.bindery.requestfactory.shared.impl.BaseProxyCategory;
import com.google.web.bindery.requestfactory.shared.impl.Constants;
import com.google.web.bindery.requestfactory.shared.impl.EntityCodex;
import com.google.web.bindery.requestfactory.shared.impl.EntityProxyCategory;
import com.google.web.bindery.requestfactory.shared.impl.SimpleProxyId;
import com.google.web.bindery.requestfactory.shared.impl.ValueProxyCategory;
import com.google.web.bindery.requestfactory.shared.messages.IdMessage.Strength;
import com.google.web.bindery.requestfactory.shared.messages.InvocationMessage;
import com.google.web.bindery.requestfactory.shared.messages.MessageFactory;
import com.google.web.bindery.requestfactory.shared.messages.OperationMessage;
import com.google.web.bindery.requestfactory.shared.messages.RequestMessage;
import com.google.web.bindery.requestfactory.shared.messages.ResponseMessage;
import com.google.web.bindery.requestfactory.shared.messages.ServerFailureMessage;
import com.google.web.bindery.requestfactory.shared.messages.ViolationMessage;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintViolation;

/**
 * Processes request payloads from a RequestFactory client. This implementation
 * is stateless. A single instance may be reused and is thread-safe.
 */
public class SimpleRequestProcessor {
  /**
   * This parameterization is so long, it improves readability to have a
   * specific type.
   */
  @SuppressWarnings("serial")
  static class IdToEntityMap extends
      HashMap<SimpleProxyId<?>, AutoBean<? extends BaseProxy>> {
  }

  /**
   * Allows the creation of properly-configured AutoBeans without having to
   * create an AutoBeanFactory with the desired annotations.
   */
  static final Configuration CONFIGURATION = new Configuration.Builder().setCategories(
      EntityProxyCategory.class, ValueProxyCategory.class,
      BaseProxyCategory.class).setNoWrap(EntityProxyId.class).build();

  /**
   * Vends message objects.
   */
  static final MessageFactory FACTORY = AutoBeanFactorySource.create(MessageFactory.class);

  static String fromBase64(String encoded) {
    try {
      return new String(Base64Utils.fromBase64(encoded), "UTF-8");
    } catch (UnsupportedEncodingException e) {
      throw new UnexpectedException(e);
    }
  }

  static String toBase64(String data) {
    try {
      return Base64Utils.toBase64(data.getBytes("UTF-8"));
    } catch (UnsupportedEncodingException e) {
      throw new UnexpectedException(e);
    }
  }

  private ExceptionHandler exceptionHandler = new DefaultExceptionHandler();
  private final ServiceLayer service;

  public SimpleRequestProcessor(ServiceLayer serviceLayer) {
    this.service = serviceLayer;
  }

  /**
   * Process a payload sent by a RequestFactory client.
   * 
   * @param payload the payload sent by the client
   * @return a payload to return to the client
   */
  public String process(String payload) {
    RequestMessage req = AutoBeanCodex.decode(FACTORY, RequestMessage.class,
        payload).as();
    AutoBean<ResponseMessage> responseBean = FACTORY.response();
    try {
      process(req, responseBean.as());
    } catch (ReportableException e) {
      e.printStackTrace();
      // Create a new response envelope, since the state is unknown
      responseBean = FACTORY.response();
      responseBean.as().setGeneralFailure(createFailureMessage(e).as());
    }
    // Return a JSON-formatted payload
    return AutoBeanCodex.encode(responseBean).getPayload();
  }

  public void setExceptionHandler(ExceptionHandler exceptionHandler) {
    this.exceptionHandler = exceptionHandler;
  }

  /**
   * Encode a list of objects into a self-contained message that can be used for
   * out-of-band communication.
   */
  <T> Splittable createOobMessage(List<T> domainValues) {
    RequestState state = new RequestState(service);

    List<Splittable> encodedValues = new ArrayList<Splittable>(
        domainValues.size());
    for (T domainValue : domainValues) {
      Object clientValue;
      if (domainValue == null) {
        clientValue = null;
      } else {
        Class<?> clientType = service.resolveClientType(domainValue.getClass(),
            BaseProxy.class, true);
        clientValue = state.getResolver().resolveClientValue(domainValue,
            clientType, Collections.<String> emptySet());
      }
      encodedValues.add(EntityCodex.encode(state, clientValue));
    }

    IdToEntityMap map = new IdToEntityMap();
    map.putAll(state.beans);
    List<OperationMessage> operations = new ArrayList<OperationMessage>();
    createReturnOperations(operations, state, map);

    InvocationMessage invocation = FACTORY.invocation().as();
    invocation.setParameters(encodedValues);

    AutoBean<RequestMessage> bean = FACTORY.request();
    RequestMessage resp = bean.as();
    resp.setInvocations(Collections.singletonList(invocation));
    resp.setOperations(operations);
    return AutoBeanCodex.encode(bean);
  }

  /**
   * Decode an out-of-band message.
   */
  <T> List<T> decodeOobMessage(Class<T> domainClass, Splittable payload) {
    Class<?> proxyType = service.resolveClientType(domainClass,
        BaseProxy.class, true);
    RequestState state = new RequestState(service);
    RequestMessage message = AutoBeanCodex.decode(FACTORY,
        RequestMessage.class, payload).as();
    processOperationMessages(state, message);
    List<Object> decoded = decodeInvocationArguments(state,
        message.getInvocations().get(0).getParameters(),
        new Class<?>[] {proxyType}, new Type[] {domainClass});

    @SuppressWarnings("unchecked")
    List<T> toReturn = (List<T>) decoded;
    return toReturn;
  }

  /**
   * Main processing method.
   */
  void process(RequestMessage req, ResponseMessage resp) {
    final RequestState source = new RequestState(service);
    // Apply operations
    processOperationMessages(source, req);

    // Validate entities
    List<ViolationMessage> errorMessages = validateEntities(source);

    if (!errorMessages.isEmpty()) {
      resp.setViolations(errorMessages);
      return;
    }

    RequestState returnState = new RequestState(source);

    // Invoke methods
    List<Splittable> invocationResults = new ArrayList<Splittable>();
    List<Boolean> invocationSuccess = new ArrayList<Boolean>();
    processInvocationMessages(source, req, invocationResults,
        invocationSuccess, returnState);

    // Store return objects
    List<OperationMessage> operations = new ArrayList<OperationMessage>();
    IdToEntityMap toProcess = new IdToEntityMap();
    toProcess.putAll(source.beans);
    toProcess.putAll(returnState.beans);
    createReturnOperations(operations, returnState, toProcess);

    assert invocationResults.size() == invocationSuccess.size();
    if (!invocationResults.isEmpty()) {
      resp.setInvocationResults(invocationResults);
      resp.setStatusCodes(invocationSuccess);
    }
    if (!operations.isEmpty()) {
      resp.setOperations(operations);
    }
  }

  private AutoBean<ServerFailureMessage> createFailureMessage(
      ReportableException e) {
    ServerFailure failure = exceptionHandler.createServerFailure(e.getCause() == null
        ? e : e.getCause());
    AutoBean<ServerFailureMessage> bean = FACTORY.failure();
    ServerFailureMessage msg = bean.as();
    msg.setExceptionType(failure.getExceptionType());
    msg.setMessage(failure.getMessage());
    msg.setStackTrace(failure.getStackTraceString());
    msg.setFatal(failure.isFatal());
    return bean;
  }

  private void createReturnOperations(List<OperationMessage> operations,
      RequestState returnState, IdToEntityMap toProcess) {
    for (Map.Entry<SimpleProxyId<?>, AutoBean<? extends BaseProxy>> entry : toProcess.entrySet()) {
      SimpleProxyId<?> id = entry.getKey();

      AutoBean<? extends BaseProxy> bean = entry.getValue();
      Object domainObject = bean.getTag(Constants.DOMAIN_OBJECT);
      WriteOperation writeOperation;

      if (id.isEphemeral()) {
        // See if the entity has been persisted in the meantime
        returnState.getResolver().resolveClientValue(domainObject,
            id.getProxyClass(), Collections.<String> emptySet());
      }

      if (id.isEphemeral() || id.isSynthetic() || domainObject == null) {
        // If the object isn't persistent, there's no reason to send an update
        writeOperation = null;
      } else if (!service.isLive(domainObject)) {
        writeOperation = WriteOperation.DELETE;
      } else if (id.wasEphemeral()) {
        writeOperation = WriteOperation.PERSIST;
      } else {
        writeOperation = WriteOperation.UPDATE;
      }

      Splittable version = null;
      if (writeOperation == WriteOperation.PERSIST
          || writeOperation == WriteOperation.UPDATE) {
        /*
         * If we're sending an operation, the domain object must be persistent.
         * This means that it must also have a non-null version.
         */
        Object domainVersion = service.getVersion(domainObject);
        if (domainVersion == null) {
          throw new UnexpectedException("The persisted entity with id "
              + service.getId(domainObject) + " has a null version", null);
        }
        version = returnState.flatten(domainVersion);
      }

      boolean inResponse = bean.getTag(Constants.IN_RESPONSE) != null;

      /*
       * Don't send any data back to the client for an update on an object that
       * isn't part of the response payload when the client's version matches
       * the domain version.
       */
      if (WriteOperation.UPDATE.equals(writeOperation) && !inResponse) {
        String previousVersion = bean.<String> getTag(Constants.VERSION_PROPERTY_B64);
        if (version != null && previousVersion != null
            && version.equals(fromBase64(previousVersion))) {
          continue;
        }
      }

      OperationMessage op = FACTORY.operation().as();

      /*
       * Send a client id if the id is ephemeral or was previously associated
       * with a client id.
       */
      if (id.wasEphemeral()) {
        op.setClientId(id.getClientId());
      }

      op.setOperation(writeOperation);

      // Only send properties for entities that are part of the return graph
      if (inResponse) {
        Map<String, Splittable> propertyMap = new LinkedHashMap<String, Splittable>();
        // Add all non-null properties to the serialized form
        Map<String, Object> diff = AutoBeanUtils.getAllProperties(bean);
        for (Map.Entry<String, Object> d : diff.entrySet()) {
          Object value = d.getValue();
          if (value != null) {
            propertyMap.put(d.getKey(), EntityCodex.encode(returnState, value));
          }
        }
        op.setPropertyMap(propertyMap);
      }

      if (!id.isEphemeral() && !id.isSynthetic()) {
        // Send the server address only for persistent objects
        op.setServerId(toBase64(id.getServerId()));
      }

      if (id.isSynthetic()) {
        op.setStrength(Strength.SYNTHETIC);
        op.setSyntheticId(id.getSyntheticId());
      } else if (id.isEphemeral()) {
        op.setStrength(Strength.EPHEMERAL);
      }

      op.setTypeToken(service.resolveTypeToken(id.getProxyClass()));
      if (version != null) {
        op.setVersion(toBase64(version.getPayload()));
      }

      operations.add(op);
    }
  }

  /**
   * Decode the arguments to pass into the domain method. If the domain method
   * is not static, the instance object will be in the 0th position.
   */
  private List<Object> decodeInvocationArguments(RequestState source,
      InvocationMessage invocation, Method contextMethod) {
    boolean isStatic = Request.class.isAssignableFrom(contextMethod.getReturnType());
    int baseLength = contextMethod.getParameterTypes().length;
    int length = baseLength + (isStatic ? 0 : 1);
    int offset = isStatic ? 0 : 1;
    Class<?>[] contextArgs = new Class<?>[length];
    Type[] genericArgs = new Type[length];

    if (!isStatic) {
      genericArgs[0] = TypeUtils.getSingleParameterization(
          InstanceRequest.class, contextMethod.getGenericReturnType());
      contextArgs[0] = TypeUtils.ensureBaseType(genericArgs[0]);
    }
    System.arraycopy(contextMethod.getParameterTypes(), 0, contextArgs, offset,
        baseLength);
    System.arraycopy(contextMethod.getGenericParameterTypes(), 0, genericArgs,
        offset, baseLength);

    List<Object> args = decodeInvocationArguments(source,
        invocation.getParameters(), contextArgs, genericArgs);
    return args;
  }

  /**
   * Handles instance invocations as the instance at the 0th parameter.
   */
  private List<Object> decodeInvocationArguments(RequestState source,
      List<Splittable> parameters, Class<?>[] contextArgs, Type[] genericArgs) {
    if (parameters == null) {
      // Can't return Collections.emptyList() because this must be mutable
      return new ArrayList<Object>();
    }

    assert parameters.size() == contextArgs.length;
    List<Object> args = new ArrayList<Object>(contextArgs.length);
    for (int i = 0, j = contextArgs.length; i < j; i++) {
      Class<?> type = contextArgs[i];
      Class<?> elementType = null;
      Splittable split;
      if (Collection.class.isAssignableFrom(type)) {
        elementType = TypeUtils.ensureBaseType(TypeUtils.getSingleParameterization(
            Collection.class, genericArgs[i]));
        split = parameters.get(i);
      } else {
        split = parameters.get(i);
      }
      Object arg = EntityCodex.decode(source, type, elementType, split);
      arg = source.getResolver().resolveDomainValue(arg,
          !EntityProxyId.class.equals(contextArgs[i]));
      args.add(arg);
    }

    return args;
  }

  private void processInvocationMessages(RequestState state,
      RequestMessage req, List<Splittable> results, List<Boolean> success,
      RequestState returnState) {
    List<InvocationMessage> invocations = req.getInvocations();
    if (invocations == null) {
      // No method invocations which can happen via RequestContext.fire()
      return;
    }
    for (InvocationMessage invocation : invocations) {
      try {
        // Find the Method
        String[] operation = invocation.getOperation().split("::");
        Method contextMethod = service.resolveRequestContextMethod(
            operation[0], operation[1]);
        if (contextMethod == null) {
          throw new UnexpectedException("Cannot resolve operation "
              + invocation.getOperation(), null);
        }
        Method domainMethod = service.resolveDomainMethod(contextMethod);
        if (domainMethod == null) {
          throw new UnexpectedException("Cannot resolve domain method "
              + invocation.getOperation(), null);
        }

        // Compute the arguments
        List<Object> args = decodeInvocationArguments(state, invocation,
            contextMethod);
        // Possibly use a ServiceLocator
        if (service.requiresServiceLocator(contextMethod, domainMethod)) {
          Object serviceInstance = service.createServiceInstance(contextMethod,
              domainMethod);
          args.add(0, serviceInstance);
        }
        // Invoke it
        Object returnValue = service.invoke(domainMethod, args.toArray());

        // Convert domain object to client object
        Type requestReturnType = service.getRequestReturnType(contextMethod);
        returnValue = state.getResolver().resolveClientValue(returnValue,
            requestReturnType, invocation.getPropertyRefs());

        // Convert the client object to a string
        results.add(EntityCodex.encode(returnState, returnValue));
        success.add(true);
      } catch (ReportableException e) {
        results.add(AutoBeanCodex.encode(createFailureMessage(e)));
        success.add(false);
      }
    }
  }

  private void processOperationMessages(final RequestState state,
      RequestMessage req) {
    List<OperationMessage> operations = req.getOperations();
    if (operations == null) {
      return;
    }

    List<AutoBean<? extends BaseProxy>> beans = state.getBeansForPayload(operations);
    assert operations.size() == beans.size();

    Iterator<OperationMessage> itOp = operations.iterator();
    for (AutoBean<? extends BaseProxy> bean : beans) {
      OperationMessage operation = itOp.next();
      // Save the client's version information to reduce payload size later
      bean.setTag(Constants.VERSION_PROPERTY_B64, operation.getVersion());

      // Load the domain object with properties, if it exists
      final Object domain = bean.getTag(Constants.DOMAIN_OBJECT);
      if (domain != null) {
        // Apply any property updates
        final Map<String, Splittable> flatValueMap = operation.getPropertyMap();
        if (flatValueMap != null) {
          bean.accept(new AutoBeanVisitor() {
            @Override
            public boolean visitReferenceProperty(String propertyName,
                AutoBean<?> value, PropertyContext ctx) {
              // containsKey to distinguish null from unknown
              if (flatValueMap.containsKey(propertyName)) {
                Class<?> elementType = ctx instanceof CollectionPropertyContext
                    ? ((CollectionPropertyContext) ctx).getElementType() : null;
                Object newValue = EntityCodex.decode(state, ctx.getType(),
                    elementType, flatValueMap.get(propertyName));
                Object resolved = state.getResolver().resolveDomainValue(
                    newValue, false);
                service.setProperty(domain, propertyName,
                    service.resolveDomainClass(ctx.getType()), resolved);
              }
              return false;
            }

            @Override
            public boolean visitValueProperty(String propertyName,
                Object value, PropertyContext ctx) {
              if (flatValueMap.containsKey(propertyName)) {
                Splittable split = flatValueMap.get(propertyName);
                Object newValue = ValueCodex.decode(ctx.getType(), split);
                Object resolved = state.getResolver().resolveDomainValue(
                    newValue, false);
                service.setProperty(domain, propertyName, ctx.getType(),
                    resolved);
              }
              return false;
            }
          });
        }
      }
    }
  }

  /**
   * Validate all of the entities referenced in a RequestState.
   */
  private List<ViolationMessage> validateEntities(RequestState source) {
    List<ViolationMessage> errorMessages = new ArrayList<ViolationMessage>();
    for (Map.Entry<SimpleProxyId<?>, AutoBean<? extends BaseProxy>> entry : source.beans.entrySet()) {
      AutoBean<? extends BaseProxy> bean = entry.getValue();
      Object domainObject = bean.getTag(Constants.DOMAIN_OBJECT);

      // The object could have been deleted
      if (domainObject != null) {
        Set<ConstraintViolation<Object>> errors = service.validate(domainObject);
        if (errors != null && !errors.isEmpty()) {
          SimpleProxyId<?> id = entry.getKey();
          for (ConstraintViolation<Object> error : errors) {
            ViolationMessage message = FACTORY.violation().as();
            message.setClientId(id.getClientId());
            message.setMessage(error.getMessage());
            message.setPath(error.getPropertyPath().toString());
            if (id.isEphemeral()) {
              message.setClientId(id.getClientId());
              message.setStrength(Strength.EPHEMERAL);
            } else {
              message.setServerId(toBase64(id.getServerId()));
            }
            message.setTypeToken(service.resolveTypeToken(id.getProxyClass()));
            errorMessages.add(message);
          }
        }
      }
    }
    return errorMessages;
  }
}
