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

import com.google.gwt.autobean.server.AutoBeanFactoryMagic;
import com.google.gwt.autobean.shared.AutoBean;
import com.google.gwt.autobean.shared.AutoBeanCodex;
import com.google.gwt.autobean.shared.Splittable;
import com.google.gwt.autobean.shared.ValueCodex;
import com.google.gwt.autobean.shared.impl.StringQuoter;
import com.google.gwt.requestfactory.server.SimpleRequestProcessor.IdToEntityMap;
import com.google.gwt.requestfactory.shared.BaseProxy;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.ValueProxy;
import com.google.gwt.requestfactory.shared.impl.Constants;
import com.google.gwt.requestfactory.shared.impl.EntityCodex;
import com.google.gwt.requestfactory.shared.impl.IdFactory;
import com.google.gwt.requestfactory.shared.impl.MessageFactoryHolder;
import com.google.gwt.requestfactory.shared.impl.SimpleProxyId;
import com.google.gwt.requestfactory.shared.messages.IdMessage;
import com.google.gwt.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.
 *
 * <p><span style='color:red'>RequestFactory has moved to
 * <code>com.google.web.bindery.requestfactory</code>.  This package will be
 * removed in a future version of GWT.</span></p>
 */
@Deprecated
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 = AutoBeanFactoryMagic.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;
  }
}
