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

import static com.google.web.bindery.requestfactory.shared.impl.BaseProxyCategory.stableId;
import static com.google.web.bindery.requestfactory.shared.impl.Constants.REQUEST_CONTEXT_STATE;
import static com.google.web.bindery.requestfactory.shared.impl.Constants.STABLE_ID;

import com.google.web.bindery.autobean.shared.AutoBean;
import com.google.web.bindery.autobean.shared.AutoBeanCodex;
import com.google.web.bindery.autobean.shared.AutoBeanFactory;
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.shared.impl.AbstractAutoBean;
import com.google.web.bindery.autobean.shared.impl.EnumMap;
import com.google.web.bindery.autobean.shared.impl.StringQuoter;
import com.google.web.bindery.event.shared.UmbrellaException;
import com.google.web.bindery.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxyChange;
import com.google.web.bindery.requestfactory.shared.EntityProxyId;
import com.google.web.bindery.requestfactory.shared.FanoutReceiver;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.RequestTransport.TransportReceiver;
import com.google.web.bindery.requestfactory.shared.ServerFailure;
import com.google.web.bindery.requestfactory.shared.WriteOperation;
import com.google.web.bindery.requestfactory.shared.impl.posers.DatePoser;
import com.google.web.bindery.requestfactory.shared.messages.IdMessage;
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.JsonRpcRequest;
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.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Path;
import javax.validation.metadata.ConstraintDescriptor;

/**
 * Base implementations for RequestContext services.
 */
public abstract class AbstractRequestContext implements RequestContext, EntityCodex.EntitySource {
  /**
   * Allows the payload dialect to be injected into the AbstractRequestContext without the caller
   * needing to be concerned with how the implementation object is instantiated.
   */
  public enum Dialect {
    STANDARD {
      @Override
      DialectImpl create(AbstractRequestContext context) {
        return context.new StandardPayloadDialect();
      }
    },
    JSON_RPC {
      @Override
      DialectImpl create(AbstractRequestContext context) {
        return context.new JsonRpcPayloadDialect();
      }
    };
    abstract DialectImpl create(AbstractRequestContext context);
  }

  /**
   * Encapsulates all state contained by the AbstractRequestContext.
   */
  protected static class State {
    /**
     * Supports the case where chained contexts are used and a response comes back from the server
     * with a proxy type not reachable from the canonical context.
     */
    public Set<AbstractRequestContext> appendedContexts;
    public final AbstractRequestContext canonical;
    public final DialectImpl dialect;
    public FanoutReceiver<Void> fanout;
    /**
     * When {@code true} the {@link AbstractRequestContext#fire()} method will be a no-op.
     */
    public boolean fireDisabled;
    public final List<AbstractRequest<?, ?>> invocations = new ArrayList<AbstractRequest<?, ?>>();

    public boolean locked;
    /**
     * See http://code.google.com/p/google-web-toolkit/issues/detail?id=5952.
     */
    public boolean diffing;
    /**
     * A map of all EntityProxies that the RequestContext has interacted with. Objects are placed
     * into this map by being returned from {@link #create}, passed into {@link #edit}, or used as
     * an invocation argument.
     */
    public final Map<SimpleProxyId<?>, AutoBean<? extends BaseProxy>> editedProxies =
        new LinkedHashMap<SimpleProxyId<?>, AutoBean<? extends BaseProxy>>();
    /**
     * A map that contains the canonical instance of an entity to return in the return graph, since
     * this is built from scratch.
     */
    public final Map<SimpleProxyId<?>, AutoBean<?>> returnedProxies =
        new HashMap<SimpleProxyId<?>, AutoBean<?>>();

    public final AbstractRequestFactory requestFactory;

    /**
     * A map that allows us to handle the case where the server has sent back an unpersisted entity.
     * Because we assume that the server is stateless, the client will need to swap out the
     * request-local ids with a regular client-allocated id.
     */
    public final Map<Integer, SimpleProxyId<?>> syntheticIds =
        new HashMap<Integer, SimpleProxyId<?>>();

    public State(AbstractRequestFactory requestFactory, DialectImpl dialect,
        AbstractRequestContext canonical) {
      this.requestFactory = requestFactory;
      this.canonical = canonical;
      this.dialect = dialect;
    }

    public void addContext(AbstractRequestContext ctx) {
      if (appendedContexts == null) {
        appendedContexts = Collections.singleton(ctx);
      } else {
        if (appendedContexts.size() == 1) {
          appendedContexts = new LinkedHashSet<AbstractRequestContext>(appendedContexts);
        }
        appendedContexts.add(ctx);
      }
    }

    public AbstractRequestContext getCanonicalContext() {
      return canonical;
    }

    public boolean isClean() {
      return editedProxies.isEmpty() && invocations.isEmpty() && !locked
          && returnedProxies.isEmpty() && syntheticIds.isEmpty();
    }

    public boolean isCompatible(State state) {
      // Object comparison intentional
      return requestFactory == state.requestFactory
          && dialect.getClass().equals(state.dialect.getClass());
    }
  }

  interface DialectImpl {

    void addInvocation(AbstractRequest<?, ?> request);

    String makePayload();

    void processPayload(Receiver<Void> receiver, String payload);
  }

  class JsonRpcPayloadDialect implements DialectImpl {
    /**
     * Called by generated subclasses to enqueue a method invocation.
     */
    public void addInvocation(AbstractRequest<?, ?> request) {
      /*
       * TODO(bobv): Support for multiple invocations per request needs to be ironed out. Once this
       * is done, addInvocation() can be removed from the DialectImpl interface and restored to to
       * AbstractRequestContext.
       */
      if (!state.invocations.isEmpty()) {
        throw new RuntimeException("Only one invocation per request, pending backend support");
      }
      state.invocations.add(request);
      for (Object arg : request.getRequestData().getOrderedParameters()) {
        retainArg(arg);
      }
    }

    public String makePayload() {
      RequestData data = state.invocations.get(0).getRequestData();

      AutoBean<JsonRpcRequest> bean = MessageFactoryHolder.FACTORY.jsonRpcRequest();
      JsonRpcRequest request = bean.as();

      request.setVersion("2.0");
      request.setApiVersion(data.getApiVersion());
      request.setId(payloadId++);

      Map<String, Splittable> params = new HashMap<String, Splittable>();
      for (Map.Entry<String, Object> entry : data.getNamedParameters().entrySet()) {
        Object obj = entry.getValue();
        Splittable value = encode(obj);
        params.put(entry.getKey(), value);
      }
      if (data.getRequestResource() != null) {
        params.put("resource", encode(data.getRequestResource()));
      }
      request.setParams(params);
      request.setMethod(data.getOperation());

      return AutoBeanCodex.encode(bean).getPayload();
    }

    public void processPayload(Receiver<Void> receiver, String payload) {
      Splittable raw = StringQuoter.split(payload);

      @SuppressWarnings("unchecked")
      Receiver<Object> callback = (Receiver<Object>) state.invocations.get(0).getReceiver();

      if (!raw.isNull("error")) {
        Splittable error = raw.get("error");
        ServerFailure failure =
            new ServerFailure(error.get("message").asString(), error.get("code").asString(),
                payload, true);
        fail(receiver, failure);
        return;
      }

      Splittable result = raw.get("result");
      @SuppressWarnings("unchecked")
      Class<BaseProxy> target =
          (Class<BaseProxy>) state.invocations.get(0).getRequestData().getReturnType();

      SimpleProxyId<BaseProxy> id = getRequestFactory().allocateId(target);
      AutoBean<BaseProxy> bean = createProxy(target, id, true);
      // XXX expose this as a proper API
      ((AbstractAutoBean<?>) bean).setData(result);
      // AutoBeanCodex.decodeInto(result, bean);

      if (callback != null) {
        callback.onSuccess(bean.as());
      }
      if (receiver != null) {
        receiver.onSuccess(null);
      }
    }

    Splittable encode(Object obj) {
      if (obj == null) {
        return Splittable.NULL;
      } else if (obj instanceof Collection) {
        return collectionEncode((Collection<?>) obj);
      }
      return nonCollectionEncode(obj);
    }

    private Splittable collectionEncode(Collection<?> collection) {
      StringBuilder sb = new StringBuilder("[");
      Iterator<?> it = collection.iterator();
      if (it.hasNext()) {
        // TODO: Allow for the encoding of nested collections. See issue 5974.
        sb.append(nonCollectionEncode(it.next()).getPayload());
        while (it.hasNext()) {
          sb.append(",");
          // TODO: Allow for the encoding of nested collections. See issue 5974.
          sb.append(nonCollectionEncode(it.next()).getPayload());
        }
      }
      sb.append("]");

      return StringQuoter.split(sb.toString());
    }

    private Splittable nonCollectionEncode(Object obj) {
      if (obj instanceof Collection) {
        // TODO: Allow for the encoding of nested collections. See issue 5974.
        // Once we do this, this can turn into an assert.
        throw new RuntimeException(
            "Unable to encode request as JSON payload; Request methods must have parameters of the form List<T> or Set<T>, where T is a scalar (non-collection) type.");
      }
      Splittable value;
      if (obj instanceof Enum && getAutoBeanFactory() instanceof EnumMap) {
        value = ValueCodex.encode(((EnumMap) getAutoBeanFactory()).getToken((Enum<?>) obj));
      } else if (ValueCodex.canDecode(obj.getClass())) {
        value = ValueCodex.encode(obj);
      } else {
        // XXX user-provided implementation of interface?
        value = AutoBeanCodex.encode(AutoBeanUtils.getAutoBean(obj));
      }
      return value;
    }
  }

  class StandardPayloadDialect implements DialectImpl {

    /**
     * Called by generated subclasses to enqueue a method invocation.
     */
    public void addInvocation(AbstractRequest<?, ?> request) {
      state.invocations.add(request);
      for (Object arg : request.getRequestData().getOrderedParameters()) {
        retainArg(arg);
      }
    }

    /**
     * Assemble all of the state that has been accumulated in this context. This includes:
     * <ul>
     * <li>Diffs accumulated on objects passed to {@link #edit}.
     * <li>Invocations accumulated as Request subtypes passed to {@link #addInvocation}.
     * </ul>
     */
    public String makePayload() {
      // Get the factory from the runtime-specific holder.
      MessageFactory f = MessageFactoryHolder.FACTORY;

      List<OperationMessage> operations = makePayloadOperations();
      List<InvocationMessage> invocationMessages = makePayloadInvocations();

      // Create the outer envelope message
      AutoBean<RequestMessage> bean = f.request();
      RequestMessage requestMessage = bean.as();
      requestMessage.setRequestFactory(getRequestFactory().getFactoryTypeToken());
      if (!invocationMessages.isEmpty()) {
        requestMessage.setInvocations(invocationMessages);
      }
      if (!operations.isEmpty()) {
        requestMessage.setOperations(operations);
      }
      return AutoBeanCodex.encode(bean).getPayload();
    }

    public void processPayload(final Receiver<Void> receiver, String payload) {
      ResponseMessage response =
          AutoBeanCodex.decode(MessageFactoryHolder.FACTORY, ResponseMessage.class, payload).as();
      if (response.getGeneralFailure() != null) {
        ServerFailureMessage failure = response.getGeneralFailure();
        ServerFailure fail =
            new ServerFailure(failure.getMessage(), failure.getExceptionType(), failure
                .getStackTrace(), failure.isFatal());

        fail(receiver, fail);
        return;
      }

      // Process violations and then stop
      if (response.getViolations() != null) {
        Set<ConstraintViolation<?>> errors = new HashSet<ConstraintViolation<?>>();
        for (ViolationMessage message : response.getViolations()) {
          errors.add(new MyConstraintViolation(message));
        }

        violation(receiver, errors);
        return;
      }

      // Process operations
      processReturnOperations(response);

      // Send return values
      Set<Throwable> causes = null;
      for (int i = 0, j = state.invocations.size(); i < j; i++) {
        try {
          if (response.getStatusCodes().get(i)) {
            state.invocations.get(i).onSuccess(response.getInvocationResults().get(i));
          } else {
            ServerFailureMessage failure =
                AutoBeanCodex.decode(MessageFactoryHolder.FACTORY, ServerFailureMessage.class,
                    response.getInvocationResults().get(i)).as();
            state.invocations.get(i).onFail(
                new ServerFailure(failure.getMessage(), failure.getExceptionType(), failure
                    .getStackTrace(), failure.isFatal()));
          }
        } catch (Throwable t) {
          if (causes == null) {
            causes = new HashSet<Throwable>();
          }
          causes.add(t);
        }
      }

      if (receiver != null) {
        try {
          receiver.onSuccess(null);
        } catch (Throwable t) {
          if (causes == null) {
            causes = new HashSet<Throwable>();
          }
          causes.add(t);
        }
      }
      // After success, shut down the context
      state.editedProxies.clear();
      state.invocations.clear();
      state.returnedProxies.clear();

      if (causes != null) {
        throw new UmbrellaException(causes);
      }
    }
  }

  private class MyConstraintViolation implements ConstraintViolation<BaseProxy> {
    private final BaseProxy leafBean;
    private final String messageTemplate;
    private final String message;
    private final String path;
    private final BaseProxy rootBean;
    private final Class<? extends BaseProxy> rootBeanClass;

    public MyConstraintViolation(ViolationMessage msg) {
      AutoBean<? extends BaseProxy> leafProxy = findEditedProxy(msg.getLeafBeanId());
      leafBean = leafProxy == null ? null : leafProxy.as();
      message = msg.getMessage();
      messageTemplate = msg.getMessageTemplate();
      path = msg.getPath();
      AutoBean<? extends BaseProxy> rootProxy = findEditedProxy(msg.getRootBeanId());
      rootBeanClass = rootProxy.getType();
      rootBean = rootProxy.as();
    }

    public ConstraintDescriptor<?> getConstraintDescriptor() {
      return null;
    }

    public Object getInvalidValue() {
      return null;
    }

    public Object getLeafBean() {
      return leafBean;
    }

    public String getMessage() {
      return message;
    }

    public String getMessageTemplate() {
      return messageTemplate;
    }

    public Path getPropertyPath() {
      return new Path() {
        public Iterator<Node> iterator() {
          return Collections.<Node> emptyList().iterator();
        }

        @Override
        public String toString() {
          return path;
        }
      };
    }

    public BaseProxy getRootBean() {
      return rootBean;
    }

    @SuppressWarnings("unchecked")
    public Class<BaseProxy> getRootBeanClass() {
      return (Class<BaseProxy>) rootBeanClass;
    }

    private AutoBean<? extends BaseProxy> findEditedProxy(IdMessage idMessage) {
      // Support violations for value objects.
      SimpleProxyId<BaseProxy> rootId = getId(idMessage);

      // The stub is empty, since we don't process any OperationMessages
      AutoBean<BaseProxy> stub = getProxyForReturnPayloadGraph(rootId);

      // So pick up the instance that we just sent to the server
      return state.editedProxies.get(BaseProxyCategory.stableId(stub));
    }
  }

  private static final WriteOperation[] DELETE_ONLY = {WriteOperation.DELETE};
  private static final WriteOperation[] PERSIST_AND_UPDATE = {
      WriteOperation.PERSIST, WriteOperation.UPDATE};
  private static final WriteOperation[] UPDATE_ONLY = {WriteOperation.UPDATE};
  private static int payloadId = 100;

  private State state;

  protected AbstractRequestContext(AbstractRequestFactory factory, Dialect dialect) {
    setState(new State(factory, dialect.create(this), this));
  }

  public <T extends RequestContext> T append(T other) {
    AbstractRequestContext child = (AbstractRequestContext) other;
    if (!state.isCompatible(child.state)) {
      throw new IllegalStateException(getClass().getName() + " and " + child.getClass().getName()
          + " are not compatible");
    }
    if (!child.state.isClean()) {
      throw new IllegalStateException("The provided RequestContext has been changed");
    }
    child.setState(state);
    return other;
  }

  /**
   * Create a new object, with an ephemeral id.
   */
  public <T extends BaseProxy> T create(Class<T> clazz) {
    checkLocked();

    SimpleProxyId<T> id = state.requestFactory.allocateId(clazz);
    AutoBean<T> created = createProxy(clazz, id, false);
    return takeOwnership(created);
  }

  public <T extends BaseProxy> T edit(T object) {
    return editProxy(object);
  }

  /**
   * Take ownership of a proxy instance and make it editable.
   */
  public <T extends BaseProxy> T editProxy(T object) {
    AutoBean<T> bean = checkStreamsNotCrossed(object);
    checkLocked();

    @SuppressWarnings("unchecked")
    AutoBean<T> previouslySeen =
        (AutoBean<T>) state.editedProxies.get(BaseProxyCategory.stableId(bean));
    if (previouslySeen != null && !previouslySeen.isFrozen()) {
      /*
       * If we've seen the object before, it might be because it was passed in as a method argument.
       * This does not guarantee its mutability, so check that here before returning the cached
       * object.
       */
      return previouslySeen.as();
    }

    // Create editable copies
    AutoBean<T> parent = bean;
    bean = cloneBeanAndCollections(bean);
    bean.setTag(Constants.PARENT_OBJECT, parent);
    return bean.as();
  }

  @Override
  public <P extends EntityProxy> Request<P> find(final EntityProxyId<P> proxyId) {
    return new AbstractRequest<BaseProxy, P>(this) {
      {
        requestContext.addInvocation(this);
      }

      @Override
      protected RequestData makeRequestData() {
        // This method is normally generated, hence the ugly constructor
        return new RequestData(Constants.FIND_METHOD_OPERATION, new Object[] {proxyId},
            propertyRefs, proxyId.getProxyClass(), null);
      }
    };
  }

  /**
   * Make sure there's a default receiver so errors don't get dropped. This behavior should be
   * revisited when chaining is supported, depending on whether or not chained invocations can fail
   * independently.
   */
  public void fire() {
    boolean needsReceiver = true;
    for (AbstractRequest<?, ?> request : state.invocations) {
      if (request.hasReceiver()) {
        needsReceiver = false;
        break;
      }
    }

    if (needsReceiver) {
      doFire(new Receiver<Void>() {
        @Override
        public void onSuccess(Void response) {
          // Don't care
        }
      });
    } else {
      doFire(null);
    }
  }

  public void fire(final Receiver<Void> receiver) {
    if (receiver == null) {
      throw new IllegalArgumentException();
    }
    doFire(receiver);
  }

  /**
   * EntityCodex support.
   */
  public <Q extends BaseProxy> AutoBean<Q> getBeanForPayload(Splittable serializedProxyId) {
    IdMessage ref =
        AutoBeanCodex.decode(MessageFactoryHolder.FACTORY, IdMessage.class, serializedProxyId).as();
    @SuppressWarnings("unchecked")
    SimpleProxyId<Q> id = (SimpleProxyId<Q>) getId(ref);
    return getProxyForReturnPayloadGraph(id);
  }

  public AbstractRequestFactory getRequestFactory() {
    return state.requestFactory;
  }

  /**
   * EntityCodex support.
   */
  public Splittable getSerializedProxyId(SimpleProxyId<?> stableId) {
    AutoBean<IdMessage> bean = MessageFactoryHolder.FACTORY.id();
    IdMessage ref = bean.as();
    ref.setServerId(stableId.getServerId());
    ref.setTypeToken(getRequestFactory().getTypeToken(stableId.getProxyClass()));
    if (stableId.isSynthetic()) {
      ref.setStrength(Strength.SYNTHETIC);
      ref.setSyntheticId(stableId.getSyntheticId());
    } else if (stableId.isEphemeral()) {
      ref.setStrength(Strength.EPHEMERAL);
      ref.setClientId(stableId.getClientId());
    }
    return AutoBeanCodex.encode(bean);
  }

  public boolean isChanged() {
    /*
     * NB: Don't use the presence of ephemeral objects for this test.
     *
     * Diff the objects until one is found to be different. It's not just a
     * simple flag-check because of the possibility of "unmaking" a change, per
     * the JavaDoc.
     *
     * TODO: try to get rid of the 'diffing' flag and optimize the diffing of
     * objects: http://code.google.com/p/google-web-toolkit/issues/detail?id=7379
     */
    assert !state.diffing;
    state.diffing = true;
    try {
      for (AutoBean<? extends BaseProxy> bean : state.editedProxies.values()) {
        AutoBean<?> previous = bean.getTag(Constants.PARENT_OBJECT);
        if (previous == null) {
          // Compare to empty object
          Class<?> proxyClass = stableId(bean).getProxyClass();
          previous = getAutoBeanFactory().create(proxyClass);
        }
        if (!AutoBeanUtils.diff(previous, bean).isEmpty()) {
          return true;
        }
      }
      return false;
    } finally {
      state.diffing = false;
    }
  }

  /**
   * EntityCodex support.
   */
  public boolean isEntityType(Class<?> clazz) {
    return state.requestFactory.isEntityType(clazz);
  }

  public boolean isLocked() {
    return state.locked;
  }

  /**
   * EntityCodex support.
   */
  public boolean isValueType(Class<?> clazz) {
    return state.requestFactory.isValueType(clazz);
  }

  public void setFireDisabled(boolean disabled) {
    state.fireDisabled = disabled;
  }

  /**
   * Called by generated subclasses to enqueue a method invocation.
   */
  protected void addInvocation(AbstractRequest<?, ?> request) {
    state.dialect.addInvocation(request);
  };

  /**
   * Creates a new proxy with an assigned ID.
   *
   * @param clazz The proxy type
   * @param id The id to be assigned to the new proxy
   * @param useAppendedContexts if {@code true} use the AutoBeanFactory types associated with any
   *          contexts that have been passed into {@link #append(RequestContext)}. If {@code false},
   *          this method will only create proxy types reachable from the implemented RequestContext
   *          interface.
   * @throws IllegalArgumentException if the requested proxy type cannot be created
   */
  protected <T extends BaseProxy> AutoBean<T> createProxy(Class<T> clazz, SimpleProxyId<T> id,
      boolean useAppendedContexts) {
    AutoBean<T> created = null;
    if (useAppendedContexts) {
      for (AbstractRequestContext ctx : state.appendedContexts) {
        created = ctx.getAutoBeanFactory().create(clazz);
        if (created != null) {
          break;
        }
      }
    } else {
      created = getAutoBeanFactory().create(clazz);
    }
    if (created != null) {
      created.setTag(STABLE_ID, id);
      return created;
    }
    throw new IllegalArgumentException("Unknown proxy type " + clazz.getName());
  }

  /**
   * Invoke the appropriate {@code onFailure} callbacks, possibly throwing an
   * {@link UmbrellaException} if one or more callbacks fails.
   */
  protected void fail(Receiver<Void> receiver, ServerFailure failure) {
    reuse();
    failure.setRequestContext(this);
    Set<Throwable> causes = null;
    for (AbstractRequest<?, ?> request : new ArrayList<AbstractRequest<?, ?>>(state.invocations)) {
      try {
        request.onFail(failure);
      } catch (Throwable t) {
        if (causes == null) {
          causes = new HashSet<Throwable>();
        }
        causes.add(t);
      }
    }
    if (receiver != null) {
      try {
        receiver.onFailure(failure);
      } catch (Throwable t) {
        if (causes == null) {
          causes = new HashSet<Throwable>();
        }
        causes.add(t);
      }
    }

    if (causes != null) {
      throw new UmbrellaException(causes);
    }
  }

  /**
   * Returns an AutoBeanFactory that can produce the types reachable only from this RequestContext.
   */
  protected abstract AutoBeanFactory getAutoBeanFactory();

  /**
   * Invoke the appropriate {@code onViolation} callbacks, possibly throwing an
   * {@link UmbrellaException} if one or more callbacks fails.
   */
  protected void violation(final Receiver<Void> receiver, Set<ConstraintViolation<?>> errors) {
    reuse();
    Set<Throwable> causes = null;
    for (AbstractRequest<?, ?> request : new ArrayList<AbstractRequest<?, ?>>(state.invocations)) {
      try {
        request.onViolation(errors);
      } catch (Throwable t) {
        if (causes == null) {
          causes = new HashSet<Throwable>();
        }
        causes.add(t);
      }
    }
    if (receiver != null) {
      try {
        receiver.onConstraintViolation(errors);
      } catch (Throwable t) {
        if (causes == null) {
          causes = new HashSet<Throwable>();
        }
        causes.add(t);
      }
    }

    if (causes != null) {
      throw new UmbrellaException(causes);
    }
  }

  /**
   * Resolves an IdMessage into an SimpleProxyId.
   */
  SimpleProxyId<BaseProxy> getId(IdMessage op) {
    if (Strength.SYNTHETIC.equals(op.getStrength())) {
      return allocateSyntheticId(op.getTypeToken(), op.getSyntheticId());
    }
    return state.requestFactory.getId(op.getTypeToken(), op.getServerId(), op.getClientId());
  }

  /**
   * Creates or retrieves a new canonical AutoBean to represent the given id in the returned
   * payload.
   */
  <Q extends BaseProxy> AutoBean<Q> getProxyForReturnPayloadGraph(SimpleProxyId<Q> id) {
    @SuppressWarnings("unchecked")
    AutoBean<Q> bean = (AutoBean<Q>) state.returnedProxies.get(id);
    if (bean == null) {
      Class<Q> proxyClass = id.getProxyClass();
      bean = createProxy(proxyClass, id, true);
      state.returnedProxies.put(id, bean);
    }

    return bean;
  }

  /**
   * Whether the RequestContext is currently diffing proxies.
   * <p>
   * This flag is used in {@link BaseProxyCategory} and
   * {@link EntityProxyCategory} to influence the way proxies are being
   * compared for equality, and to prevent auto-editing proxies when
   * walking reference properties.
   * <p>
   * See http://code.google.com/p/google-web-toolkit/issues/detail?id=5952
   * <p>
   * TODO: try to get rid of this flag.
   * See http://code.google.com/p/google-web-toolkit/issues/detail?id=7379
   */
  boolean isDiffing() {
    return state.diffing;
  }

  /**
   * Create a single OperationMessage that encapsulates the state of a proxy AutoBean.
   */
  AutoBean<OperationMessage> makeOperationMessage(SimpleProxyId<BaseProxy> stableId,
      AutoBean<?> proxyBean, boolean useDelta) {

    // The OperationMessages describes operations on exactly one entity
    AutoBean<OperationMessage> toReturn = MessageFactoryHolder.FACTORY.operation();
    OperationMessage operation = toReturn.as();
    operation.setTypeToken(state.requestFactory.getTypeToken(stableId.getProxyClass()));

    // Find the object to compare against
    AutoBean<?> parent;
    if (stableId.isEphemeral()) {
      // Newly-created object, use a blank object to compare against
      parent = createProxy(stableId.getProxyClass(), stableId, true);

      // Newly-created objects go into the persist operation bucket
      operation.setOperation(WriteOperation.PERSIST);
      // The ephemeral id is passed to the server
      operation.setClientId(stableId.getClientId());
      operation.setStrength(Strength.EPHEMERAL);
    } else if (stableId.isSynthetic()) {
      // Newly-created object, use a blank object to compare against
      parent = createProxy(stableId.getProxyClass(), stableId, true);

      // Newly-created objects go into the persist operation bucket
      operation.setOperation(WriteOperation.PERSIST);
      // The ephemeral id is passed to the server
      operation.setSyntheticId(stableId.getSyntheticId());
      operation.setStrength(Strength.SYNTHETIC);
    } else {
      parent = proxyBean.getTag(Constants.PARENT_OBJECT);
      // Requests involving existing objects use the persisted id
      operation.setServerId(stableId.getServerId());
      operation.setOperation(WriteOperation.UPDATE);
    }
    assert !useDelta || parent != null;

    // Send our version number to the server to cut down on future payloads
    String version = proxyBean.getTag(Constants.VERSION_PROPERTY_B64);
    if (version != null) {
      operation.setVersion(version);
    }

    Map<String, Object> diff = Collections.emptyMap();
    if (isEntityType(stableId.getProxyClass())) {
      // Compute what's changed on the client
      diff =
          useDelta ? AutoBeanUtils.diff(parent, proxyBean) : AutoBeanUtils
              .getAllProperties(proxyBean);
    } else if (isValueType(stableId.getProxyClass())) {
      // Send everything
      diff = AutoBeanUtils.getAllProperties(proxyBean);
    }

    if (!diff.isEmpty()) {
      Map<String, Splittable> propertyMap = new HashMap<String, Splittable>();
      for (Map.Entry<String, Object> entry : diff.entrySet()) {
        propertyMap.put(entry.getKey(), EntityCodex.encode(this, entry.getValue()));
      }
      operation.setPropertyMap(propertyMap);
    }
    return toReturn;
  }

  /**
   * Create a new EntityProxy from a snapshot in the return payload.
   *
   * @param id the EntityProxyId of the object
   * @param returnRecord the JSON map containing property/value pairs
   * @param operations the WriteOperation eventns to broadcast over the EventBus
   */
  <Q extends BaseProxy> Q processReturnOperation(SimpleProxyId<Q> id, OperationMessage op,
      WriteOperation... operations) {

    AutoBean<Q> toMutate = getProxyForReturnPayloadGraph(id);
    toMutate.setTag(Constants.VERSION_PROPERTY_B64, op.getVersion());

    final Map<String, Splittable> properties = op.getPropertyMap();
    if (properties != null) {
      // Apply updates
      toMutate.accept(new AutoBeanVisitor() {
        @Override
        public boolean visitReferenceProperty(String propertyName, AutoBean<?> value,
            PropertyContext ctx) {
          if (ctx.canSet()) {
            if (properties.containsKey(propertyName)) {
              Splittable raw = properties.get(propertyName);
              Object decoded = null;
              if (ctx.getType() == Map.class) {
                MapPropertyContext mapCtx = (MapPropertyContext) ctx;
                Class<?> keyType = mapCtx.getKeyType();
                Class<?> valueType = mapCtx.getValueType();
                decoded =
                    EntityCodex.decode(AbstractRequestContext.this, mapCtx.getType(), keyType,
                        valueType, raw);
              } else {
                Class<?> elementType =
                    ctx instanceof CollectionPropertyContext ? ((CollectionPropertyContext) ctx)
                        .getElementType() : null;
                decoded =
                    EntityCodex.decode(AbstractRequestContext.this, ctx.getType(), elementType, raw);
              }
              ctx.set(decoded);
            }
          }
          return false;
        }

        @Override
        public boolean visitValueProperty(String propertyName, Object value, PropertyContext ctx) {
          if (ctx.canSet()) {
            if (properties.containsKey(propertyName)) {
              Splittable raw = properties.get(propertyName);
              Object decoded = ValueCodex.decode(ctx.getType(), raw);
              /*
               * Hack for Date subtypes, consider generalizing for "custom serializers"
               */
              if (decoded != null && Date.class.equals(ctx.getType())) {
                decoded = new DatePoser((Date) decoded);
              }
              ctx.set(decoded);
            }
          }
          return false;
        }
      });
    }

    // Finished applying updates, freeze the bean
    makeImmutable(toMutate);
    Q proxy = toMutate.as();

    /*
     * Notify subscribers if the object differs from when it first came into the RequestContext.
     */
    if (operations != null && state.requestFactory.isEntityType(id.getProxyClass())) {
      for (WriteOperation writeOperation : operations) {
        if (writeOperation.equals(WriteOperation.UPDATE)
            && !state.requestFactory.hasVersionChanged(id, op.getVersion())) {
          // No updates if the server reports no change
          continue;
        }
        state.requestFactory.getEventBus().fireEventFromSource(
            new EntityProxyChange<EntityProxy>((EntityProxy) proxy, writeOperation),
            id.getProxyClass());
      }
    }
    return proxy;
  }

  /**
   * Get-or-create method for synthetic ids.
   *
   * @see #syntheticIds
   */
  private <Q extends BaseProxy> SimpleProxyId<Q> allocateSyntheticId(String typeToken,
      int syntheticId) {
    @SuppressWarnings("unchecked")
    SimpleProxyId<Q> toReturn = (SimpleProxyId<Q>) state.syntheticIds.get(syntheticId);
    if (toReturn == null) {
      toReturn =
          state.requestFactory.allocateId(state.requestFactory.<Q> getTypeFromToken(typeToken));
      state.syntheticIds.put(syntheticId, toReturn);
    }
    return toReturn;
  }

  private void checkLocked() {
    if (state.locked) {
      throw new IllegalStateException("A request is already in progress");
    }
  }

  /**
   * This method checks that a proxy object is either immutable, or already edited by this context.
   */
  private <T> AutoBean<T> checkStreamsNotCrossed(T object) {
    AutoBean<T> bean = AutoBeanUtils.getAutoBean(object);
    if (bean == null) {
      // Unexpected; some kind of foreign implementation?
      throw new IllegalArgumentException(object.getClass().getName());
    }

    State otherState = bean.getTag(REQUEST_CONTEXT_STATE);
    if (!bean.isFrozen() && otherState != this.state) {
      /*
       * This means something is way off in the weeds. If a bean is editable, it's supposed to be
       * associated with a RequestContext.
       */
      assert otherState != null : "Unfrozen bean with null RequestContext";

      /*
       * Already editing the object in another context or it would have been in the editing map.
       */
      throw new IllegalArgumentException("Attempting to edit an EntityProxy"
          + " previously edited by another RequestContext");
    }
    return bean;
  }

  /**
   * Shallow-clones an autobean and makes duplicates of the collection types. A regular
   * {@link AutoBean#clone} won't duplicate reference properties.
   */
  private <T extends BaseProxy> AutoBean<T> cloneBeanAndCollections(final AutoBean<T> toClone) {
    AutoBean<T> clone = toClone.getFactory().create(toClone.getType());
    clone.setTag(STABLE_ID, toClone.getTag(STABLE_ID));
    clone.setTag(Constants.VERSION_PROPERTY_B64, toClone.getTag(Constants.VERSION_PROPERTY_B64));
    /*
     * Take ownership here to prevent cycles in value objects from overflowing the stack.
     */
    takeOwnership(clone);
    clone.accept(new AutoBeanVisitor() {
      final Map<String, Object> values = AutoBeanUtils.getAllProperties(toClone);

      @Override
      public boolean visitCollectionProperty(String propertyName, AutoBean<Collection<?>> value,
          CollectionPropertyContext ctx) {
        // javac generics bug
        value =
            AutoBeanUtils.<Collection<?>, Collection<?>> getAutoBean((Collection<?>) values
                .get(propertyName));
        if (value != null) {
          Collection<Object> collection;
          if (List.class == ctx.getType()) {
            collection = new ArrayList<Object>();
          } else if (Set.class == ctx.getType()) {
            collection = new HashSet<Object>();
          } else {
            // Should not get here if the validator works correctly
            throw new IllegalArgumentException(ctx.getType().getName());
          }

          if (isValueType(ctx.getElementType()) || isEntityType(ctx.getElementType())) {
            /*
             * Proxies must be edited up-front so that the elements in the collection have stable
             * identity.
             */
            for (Object o : value.as()) {
              if (o == null) {
                collection.add(null);
              } else {
                collection.add(editProxy((BaseProxy) o));
              }
            }
          } else {
            // For simple values, just copy the values
            collection.addAll(value.as());
          }

          ctx.set(collection);
        }
        return false;
      }

      @Override
      public boolean visitReferenceProperty(String propertyName, AutoBean<?> value,
          PropertyContext ctx) {
        value = AutoBeanUtils.getAutoBean(values.get(propertyName));
        if (value != null) {
          if (isValueType(ctx.getType()) || isEntityType(ctx.getType())) {
            /*
             * Value proxies must be cloned upfront, since the value is replaced outright.
             */
            @SuppressWarnings("unchecked")
            AutoBean<BaseProxy> valueBean = (AutoBean<BaseProxy>) value;
            ctx.set(editProxy(valueBean.as()));
          } else {
            ctx.set(value.as());
          }
        }
        return false;
      }

      @Override
      public boolean visitValueProperty(String propertyName, Object value, PropertyContext ctx) {
        ctx.set(values.get(propertyName));
        return false;
      }
    });
    return clone;
  }

  private void doFire(Receiver<Void> receiver) {
    final Receiver<Void> finalReceiver;
    if (state.fireDisabled) {
      if (receiver != null) {
        if (state.fanout == null) {
          state.fanout = new FanoutReceiver<Void>();
        }
        state.fanout.add(receiver);
      }
      return;
    } else if (state.fanout != null) {
      if (receiver != null) {
        state.fanout.add(receiver);
      }
      finalReceiver = state.fanout;
    } else {
      finalReceiver = receiver;
    }
    checkLocked();
    state.locked = true;

    freezeEntities(true);

    String payload = state.dialect.makePayload();
    state.requestFactory.getRequestTransport().send(payload, new TransportReceiver() {
      public void onTransportFailure(ServerFailure failure) {
        fail(finalReceiver, failure);
      }

      public void onTransportSuccess(String payload) {
        state.dialect.processPayload(finalReceiver, payload);
      }
    });
  }

  /**
   * Set the frozen status of all EntityProxies owned by this context.
   */
  private void freezeEntities(boolean frozen) {
    for (AutoBean<?> bean : state.editedProxies.values()) {
      bean.setFrozen(frozen);
    }
  }

  /**
   * Make an EntityProxy immutable.
   */
  private void makeImmutable(final AutoBean<? extends BaseProxy> toMutate) {
    // Always diff'ed against itself, producing a no-op
    toMutate.setTag(Constants.PARENT_OBJECT, toMutate);
    // Act with entity-identity semantics
    toMutate.setTag(REQUEST_CONTEXT_STATE, null);
    toMutate.setFrozen(true);
  }

  /**
   * Create an InvocationMessage for each remote method call being made by the context.
   */
  private List<InvocationMessage> makePayloadInvocations() {
    MessageFactory f = MessageFactoryHolder.FACTORY;

    List<InvocationMessage> invocationMessages = new ArrayList<InvocationMessage>();
    for (AbstractRequest<?, ?> invocation : state.invocations) {
      // RequestData is produced by the generated subclass
      RequestData data = invocation.getRequestData();
      InvocationMessage message = f.invocation().as();

      // Operation; essentially a method descriptor
      message.setOperation(data.getOperation());

      // The arguments to the with() calls
      Set<String> refsToSend = data.getPropertyRefs();
      if (!refsToSend.isEmpty()) {
        message.setPropertyRefs(refsToSend);
      }

      // Parameter values or references
      List<Splittable> parameters = new ArrayList<Splittable>(data.getOrderedParameters().length);
      for (Object param : data.getOrderedParameters()) {
        parameters.add(EntityCodex.encode(this, param));
      }
      if (!parameters.isEmpty()) {
        message.setParameters(parameters);
      }

      invocationMessages.add(message);
    }
    return invocationMessages;
  }

  /**
   * Compute deltas for each entity seen by the context.
   * <p>
   * TODO(t.broyer): reduce payload size by only sending proxies that are
   * directly referenced by invocation arguments or by other proxies. For
   * backwards-compatibility with no-op requests and operation-only requests,
   * only do so when there's at least one invocation (or we can choose to
   * break backwards compatibility for those edge-cases).
   */
  private List<OperationMessage> makePayloadOperations() {
    assert isLocked();
    assert !state.diffing;
    state.diffing = true;
    try {
      List<OperationMessage> operations = new ArrayList<OperationMessage>();
      for (AutoBean<? extends BaseProxy> currentView : state.editedProxies.values()) {
        OperationMessage operation =
            makeOperationMessage(BaseProxyCategory.stableId(currentView), currentView, true).as();
        operations.add(operation);
      }
      return operations;
    } finally {
      state.diffing = false;
    }
  }

  /**
   * Process an array of OperationMessages.
   */
  private void processReturnOperations(ResponseMessage response) {
    List<OperationMessage> ops = response.getOperations();

    // If there are no observable effects, this will be null
    if (ops == null) {
      return;
    }

    for (OperationMessage op : ops) {
      SimpleProxyId<?> id = getId(op);
      WriteOperation[] toPropagate = null;

      // May be null if the server is returning an unpersisted object
      WriteOperation effect = op.getOperation();
      if (effect != null) {
        switch (effect) {
          case DELETE:
            toPropagate = DELETE_ONLY;
            break;
          case PERSIST:
            toPropagate = PERSIST_AND_UPDATE;
            break;
          case UPDATE:
            toPropagate = UPDATE_ONLY;
            break;
          default:
            // Should never reach here
            throw new RuntimeException(effect.toString());
        }
      }
      processReturnOperation(id, op, toPropagate);
    }

    assert state.returnedProxies.size() == ops.size();
  }

  /**
   * Ensures that any method arguments are retained in the context's sphere of influence.
   */
  private void retainArg(Object arg) {
    if (arg instanceof Iterable<?>) {
      for (Object o : (Iterable<?>) arg) {
        retainArg(o);
      }
    } else if (arg instanceof BaseProxy) {
      // Calling edit will validate and set up the tracking we need
      edit((BaseProxy) arg);
    }
  }

  /**
   * Returns the requests that were dequeued as part of reusing the context.
   */
  private void reuse() {
    freezeEntities(false);
    state.locked = false;
  }

  private void setState(State state) {
    this.state = state;
    state.addContext(this);
  }

  /**
   * Make the EnityProxy bean edited and owned by this RequestContext.
   */
  private <T extends BaseProxy> T takeOwnership(AutoBean<T> bean) {
    state.editedProxies.put(stableId(bean), bean);
    bean.setTag(REQUEST_CONTEXT_STATE, this.state);
    return bean.as();
  }
}
