/*
 * 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.web.bindery.autobean.shared.AutoBean;
import com.google.web.bindery.autobean.shared.AutoBeanCodex;
import com.google.web.bindery.autobean.shared.Splittable;
import com.google.web.bindery.autobean.shared.ValueCodex;
import com.google.web.bindery.autobean.shared.impl.StringQuoter;
import com.google.web.bindery.autobean.vm.AutoBeanFactorySource;
import com.google.web.bindery.requestfactory.server.SimpleRequestProcessor.IdToEntityMap;
import com.google.web.bindery.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.ValueProxy;
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.IdFactory;
import com.google.web.bindery.requestfactory.shared.impl.MessageFactoryHolder;
import com.google.web.bindery.requestfactory.shared.impl.SimpleProxyId;
import com.google.web.bindery.requestfactory.shared.messages.IdMessage;
import com.google.web.bindery.requestfactory.shared.messages.IdMessage.Strength;

import java.util.ArrayList;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Encapsulates all state relating to the processing of a single request so that
 * the SimpleRequestProcessor can be stateless.
 */
class RequestState implements EntityCodex.EntitySource {
  final IdToEntityMap beans = new IdToEntityMap();
  private final Map<Object, SimpleProxyId<?>> domainObjectsToId;
  private final IdFactory idFactory;
  private final ServiceLayer service;
  private final Resolver resolver;

  public RequestState(RequestState parent) {
    idFactory = parent.idFactory;
    domainObjectsToId = parent.domainObjectsToId;
    service = parent.service;
    resolver = new Resolver(this);
  }

  public RequestState(final ServiceLayer service) {
    this.service = service;
    idFactory = new IdFactory() {
      @Override
      public boolean isEntityType(Class<?> clazz) {
        return EntityProxy.class.isAssignableFrom(clazz);
      }

      @Override
      public boolean isValueType(Class<?> clazz) {
        return ValueProxy.class.isAssignableFrom(clazz);
      }

      @Override
      @SuppressWarnings("unchecked")
      protected <P extends BaseProxy> Class<P> getTypeFromToken(String typeToken) {
        return (Class<P>) service.resolveClass(typeToken);
      }

      @Override
      protected String getTypeToken(Class<? extends BaseProxy> clazz) {
        return service.resolveTypeToken(clazz);
      }
    };
    domainObjectsToId = new IdentityHashMap<Object, SimpleProxyId<?>>();
    resolver = new Resolver(this);
  }

  /**
   * Turn a domain value into a wire format message.
   */
  public Splittable flatten(Object domainValue) {
    Splittable flatValue;
    if (ValueCodex.canDecode(domainValue.getClass())) {
      flatValue = ValueCodex.encode(domainValue);
    } else {
      flatValue =
          new SimpleRequestProcessor(service).createOobMessage(Collections
              .singletonList(domainValue));
    }
    return flatValue;
  }

  /**
   * Get or create a BaseProxy AutoBean for the given id.
   */
  public <Q extends BaseProxy> AutoBean<Q> getBeanForPayload(SimpleProxyId<Q> id,
      Object domainObject) {
    @SuppressWarnings("unchecked")
    AutoBean<Q> toReturn = (AutoBean<Q>) beans.get(id);
    if (toReturn == null) {
      toReturn = createProxyBean(id, domainObject);
    }
    return toReturn;
  }

  /**
   * EntityCodex support.
   */
  public <Q extends BaseProxy> AutoBean<Q> getBeanForPayload(Splittable serializedProxyId) {
    IdMessage idMessage =
        AutoBeanCodex.decode(MessageFactoryHolder.FACTORY, IdMessage.class, serializedProxyId).as();
    @SuppressWarnings("unchecked")
    AutoBean<Q> toReturn =
        (AutoBean<Q>) getBeansForPayload(Collections.singletonList(idMessage)).get(0);
    return toReturn;
  }

  /**
   * Get or create BaseProxy AutoBeans for a list of id-bearing messages.
   */
  public List<AutoBean<? extends BaseProxy>> getBeansForPayload(List<? extends IdMessage> idMessages) {
    List<SimpleProxyId<?>> ids = new ArrayList<SimpleProxyId<?>>(idMessages.size());
    for (IdMessage idMessage : idMessages) {
      SimpleProxyId<?> id;
      if (Strength.SYNTHETIC.equals(idMessage.getStrength())) {
        Class<? extends BaseProxy> clazz = service.resolveClass(idMessage.getTypeToken());
        id = idFactory.allocateSyntheticId(clazz, idMessage.getSyntheticId());
      } else {
        String decodedId =
            idMessage.getServerId() == null ? null : SimpleRequestProcessor.fromBase64(idMessage
                .getServerId());
        id = idFactory.getId(idMessage.getTypeToken(), decodedId, idMessage.getClientId());
      }
      ids.add(id);
    }
    return getBeansForIds(ids);
  }

  public IdFactory getIdFactory() {
    return idFactory;
  }

  public Resolver getResolver() {
    return resolver;
  }

  /**
   * EntityCodex support. This method is identical to
   * {@link IdFactory#getHistoryToken(SimpleProxyId)} except that it
   * base64-encodes the server ids.
   * <p>
   * XXX: Merge this with AbstsractRequestContext's implementation
   */
  public Splittable getSerializedProxyId(SimpleProxyId<?> stableId) {
    AutoBean<IdMessage> bean = MessageFactoryHolder.FACTORY.id();
    IdMessage ref = bean.as();
    ref.setTypeToken(service.resolveTypeToken(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());
    } else {
      ref.setServerId(SimpleRequestProcessor.toBase64(stableId.getServerId()));
    }
    return AutoBeanCodex.encode(bean);
  }

  public ServiceLayer getServiceLayer() {
    return service;
  }

  /**
   * If the given domain object has been previously associated with an id,
   * return it.
   */
  public SimpleProxyId<?> getStableId(Object domain) {
    return domainObjectsToId.get(domain);
  }

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

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

  /**
   * Creates an AutoBean for the given id, tracking a domain object.
   */
  private <Q extends BaseProxy> AutoBean<Q> createProxyBean(SimpleProxyId<Q> id, Object domainObject) {
    AutoBean<Q> toReturn =
        AutoBeanFactorySource.createBean(id.getProxyClass(), SimpleRequestProcessor.CONFIGURATION);
    toReturn.setTag(Constants.STABLE_ID, id);
    toReturn.setTag(Constants.DOMAIN_OBJECT, domainObject);
    beans.put(id, toReturn);
    return toReturn;
  }

  /**
   * Returns the AutoBeans corresponding to the given ids, or creates them if
   * they do not yet exist.
   */
  private List<AutoBean<? extends BaseProxy>> getBeansForIds(List<SimpleProxyId<?>> ids) {
    List<Class<?>> domainClasses = new ArrayList<Class<?>>(ids.size());
    List<Object> domainIds = new ArrayList<Object>(ids.size());
    List<SimpleProxyId<?>> idsToLoad = new ArrayList<SimpleProxyId<?>>();

    /*
     * Create proxies for ephemeral or synthetic ids that we haven't seen. Queue
     * up the domain ids for entities that need to be loaded.
     */
    for (SimpleProxyId<?> id : ids) {
      Class<?> domainClass = service.resolveDomainClass(id.getProxyClass());
      if (beans.containsKey(id)) {
        // Already have a proxy for this id, no-op
      } else if (id.isEphemeral() || id.isSynthetic()) {
        // Create a new domain object for the short-lived id
        Object domain = service.createDomainObject(domainClass);
        if (domain == null) {
          throw new UnexpectedException("Could not create instance of "
              + domainClass.getCanonicalName(), null);
        }
        AutoBean<? extends BaseProxy> bean = createProxyBean(id, domain);
        beans.put(id, bean);
        domainObjectsToId.put(domain, id);
      } else {
        // Decode the domain parameter
        Splittable split = StringQuoter.split(id.getServerId());
        Class<?> param = service.getIdType(domainClass);
        Object domainParam;
        if (ValueCodex.canDecode(param)) {
          domainParam = ValueCodex.decode(param, split);
        } else {
          domainParam = new SimpleRequestProcessor(service).decodeOobMessage(param, split).get(0);
        }

        // Enqueue
        domainClasses.add(service.resolveDomainClass(id.getProxyClass()));
        domainIds.add(domainParam);
        idsToLoad.add(id);
      }
    }

    // Actually load the data
    if (!domainClasses.isEmpty()) {
      assert domainClasses.size() == domainIds.size() && domainClasses.size() == idsToLoad.size();
      List<Object> loaded = service.loadDomainObjects(domainClasses, domainIds);
      if (idsToLoad.size() != loaded.size()) {
        throw new UnexpectedException("Expected " + idsToLoad.size()
            + " objects to be loaded, got " + loaded.size(), null);
      }

      Iterator<Object> itLoaded = loaded.iterator();
      for (SimpleProxyId<?> id : idsToLoad) {
        Object domain = itLoaded.next();
        domainObjectsToId.put(domain, id);
        AutoBean<? extends BaseProxy> bean = createProxyBean(id, domain);
        beans.put(id, bean);
      }
    }

    // Construct the return value
    List<AutoBean<? extends BaseProxy>> toReturn =
        new ArrayList<AutoBean<? extends BaseProxy>>(ids.size());
    for (SimpleProxyId<?> id : ids) {
      toReturn.add(beans.get(id));
    }
    return toReturn;
  }
}
