/*
 * 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 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.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxyId;
import com.google.web.bindery.requestfactory.shared.ProxySerializer;
import com.google.web.bindery.requestfactory.shared.ProxyStore;
import com.google.web.bindery.requestfactory.shared.messages.IdMessage;
import com.google.web.bindery.requestfactory.shared.messages.OperationMessage;
import com.google.web.bindery.requestfactory.shared.messages.IdMessage.Strength;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * The default implementation of ProxySerializer.
 */
class ProxySerializerImpl extends AbstractRequestContext implements
    ProxySerializer {

  /**
   * Used internally to unwind the stack if data cannot be found in the backing
   * store.
   */
  private static class NoDataException extends RuntimeException {
  }

  private final ProxyStore store;
  /**
   * If the user wants to serialize a proxy with a non-persistent id (including
   * ValueProxy), we'll assign a synthetic id that is local to the store being
   * used.
   */
  private final Map<SimpleProxyId<?>, SimpleProxyId<?>> syntheticIds = new HashMap<SimpleProxyId<?>, SimpleProxyId<?>>();

  /**
   * The ids of proxies whose content has been reloaded.
   */
  private final Set<SimpleProxyId<?>> restored = new HashSet<SimpleProxyId<?>>();
  private final Map<SimpleProxyId<?>, AutoBean<?>> serialized = new HashMap<SimpleProxyId<?>, AutoBean<?>>();

  public ProxySerializerImpl(AbstractRequestFactory factory, ProxyStore store) {
    super(factory, Dialect.STANDARD);
    this.store = store;
  }

  public <T extends BaseProxy> T deserialize(Class<T> proxyType, String key) {
    // Fast exit to prevent getOperation from throwing an exception
    if (store.get(key) == null) {
      return null;
    }
    OperationMessage op = getOperation(proxyType, key);
    @SuppressWarnings("unchecked")
    SimpleProxyId<T> id = (SimpleProxyId<T>) getId(op);
    return doDeserialize(id);
  }

  public <T extends EntityProxy> T deserialize(EntityProxyId<T> id) {
    return doDeserialize((SimpleEntityProxyId<T>) id);
  }

  /**
   * Replace non-persistent ids with store-local ids.
   */
  @Override
  public Splittable getSerializedProxyId(SimpleProxyId<?> stableId) {
    return super.getSerializedProxyId(serializedId(stableId));
  }

  public String serialize(BaseProxy rootObject) {
    final AutoBean<? extends BaseProxy> root = AutoBeanUtils.getAutoBean(rootObject);
    if (root == null) {
      // Unexpected, some kind of foreign implementation of the BaseProxy?
      throw new IllegalArgumentException();
    }

    final SimpleProxyId<?> id = serializedId(BaseProxyCategory.stableId(root));
    // Only persistent and synthetic ids expected
    assert !id.isEphemeral() : "Unexpected ephemeral id " + id.toString();

    /*
     * Don't repeatedly serialize the same proxy, unless we're looking at a
     * mutable instance.
     */
    AutoBean<?> previous = serialized.get(id);
    if (previous == null || !previous.isFrozen()) {
      serialized.put(id, root);
      serializeOneProxy(id, root);
      root.accept(new AutoBeanVisitor() {
        @Override
        public void endVisit(AutoBean<?> bean, Context ctx) {
          // Avoid unnecessary method call
          if (bean == root) {
            return;
          }
          if (isEntityType(bean.getType()) || isValueType(bean.getType())) {
            serialize((BaseProxy) bean.as());
          }
        }

        @Override
        public void endVisitCollectionProperty(String propertyName,
            AutoBean<Collection<?>> value, CollectionPropertyContext ctx) {
          if (value == null) {
            return;
          }
          if (isEntityType(ctx.getElementType())
              || isValueType(ctx.getElementType())) {
            for (Object o : value.as()) {
              serialize((BaseProxy) o);
            }
          }
        }
      });
    }

    return getRequestFactory().getHistoryToken(id);
  }

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

  @Override
  SimpleProxyId<BaseProxy> getId(IdMessage op) {
    if (Strength.SYNTHETIC.equals(op.getStrength())) {
      return getRequestFactory().allocateSyntheticId(
          getRequestFactory().getTypeFromToken(op.getTypeToken()),
          op.getSyntheticId());
    }
    return super.getId(op);
  }

  @Override
  <Q extends BaseProxy> AutoBean<Q> getProxyForReturnPayloadGraph(
      SimpleProxyId<Q> id) {
    AutoBean<Q> toReturn = super.getProxyForReturnPayloadGraph(id);
    if (restored.add(id)) {
      /*
       * If we haven't seen the id before, use the data in the OperationMessage
       * to repopulate the properties of the canonical bean for this id.
       */
      OperationMessage op = getOperation(id.getProxyClass(),
          getRequestFactory().getHistoryToken(id));
      this.processReturnOperation(id, op);
      toReturn.setTag(Constants.STABLE_ID, super.getId(op));
    }
    return toReturn;
  }

  /**
   * Reset all temporary state.
   */
  private void clear() {
    syntheticIds.clear();
    restored.clear();
    serialized.clear();
  }

  private <T extends BaseProxy> T doDeserialize(SimpleProxyId<T> id) {
    try {
      return getProxyForReturnPayloadGraph(id).as();
    } catch (NoDataException e) {
      return null;
    } finally {
      clear();
    }
  }

  /**
   * Load the OperationMessage containing the object state from the backing
   * store.
   */
  private <T> OperationMessage getOperation(Class<T> proxyType, String key) {
    Splittable data = store.get(key);
    if (data == null) {
      throw new NoDataException();
    }

    OperationMessage op = AutoBeanCodex.decode(MessageFactoryHolder.FACTORY,
        OperationMessage.class, data).as();
    return op;
  }

  /**
   * Convert any non-persistent ids into store-local synthetic ids.
   */
  private <T extends BaseProxy> SimpleProxyId<T> serializedId(
      SimpleProxyId<T> stableId) {
    assert !stableId.isSynthetic();
    if (stableId.isEphemeral()) {
      @SuppressWarnings("unchecked")
      SimpleProxyId<T> syntheticId = (SimpleProxyId<T>) syntheticIds.get(stableId);
      if (syntheticId == null) {
        int nextId = store.nextId();
        assert nextId >= 0 : "ProxyStore.nextId() returned a negative number "
            + nextId;
        syntheticId = getRequestFactory().allocateSyntheticId(
            stableId.getProxyClass(), nextId + 1);
        syntheticIds.put(stableId, syntheticId);
      }
      return syntheticId;
    }
    return stableId;
  }

  private void serializeOneProxy(SimpleProxyId<?> idForSerialization,
      AutoBean<? extends BaseProxy> bean) {
    AutoBean<OperationMessage> op = makeOperationMessage(
        serializedId(BaseProxyCategory.stableId(bean)), bean, false);

    store.put(getRequestFactory().getHistoryToken(idForSerialization),
        AutoBeanCodex.encode(op));
  }
}
