/*
 * 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.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.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.impl.Constants;
import com.google.web.bindery.requestfactory.shared.impl.SimpleProxyId;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * Responsible for converting between domain and client entities. This class has
 * a small amount of temporary state used to handle graph cycles and assignment
 * of synthetic ids.
 * 
 * @see RequestState#getResolver()
 */
class Resolver {
  /**
   * A parameterized type with a single parameter.
   */
  private static class CollectionType implements ParameterizedType {
    private final Class<?> rawType;
    private final Class<?> elementType;

    private CollectionType(Class<?> rawType, Class<?> elementType) {
      this.rawType = rawType;
      this.elementType = elementType;
    }

    @Override
    public boolean equals(Object o) {
      if (!(o instanceof CollectionType)) {
        return false;
      }
      CollectionType other = (CollectionType) o;
      return rawType.equals(other.rawType) && elementType.equals(other.elementType);
    }

    public Type[] getActualTypeArguments() {
      return new Type[] {elementType};
    }

    public Type getOwnerType() {
      return null;
    }

    public Type getRawType() {
      return rawType;
    }

    @Override
    public int hashCode() {
      return rawType.hashCode() * 13 + elementType.hashCode() * 7;
    }
  }

  /**
   * Copies values and references from a domain object to a client object. This
   * type does not descend into referenced objects.
   */
  private class PropertyResolver extends AutoBeanVisitor {
    private final Object domainEntity;
    private final boolean isOwnerValueProxy;
    private final boolean needsSimpleValues;
    private final Set<String> propertyRefs;

    private PropertyResolver(Resolution resolution) {
      ResolutionKey key = resolution.getResolutionKey();
      this.domainEntity = key.getDomainObject();
      this.isOwnerValueProxy = state.isValueType(TypeUtils.ensureBaseType(key.requestedType));
      this.needsSimpleValues = resolution.needsSimpleValues();
      this.propertyRefs = resolution.takeWork();
    }

    @Override
    public boolean visitReferenceProperty(String propertyName, AutoBean<?> value,
        PropertyContext ctx) {
      /*
       * Send the property if the enclosing type is a ValueProxy, if the owner
       * requested the property, or if the property is a list of values.
       */
      Class<?> elementType =
          ctx instanceof CollectionPropertyContext ? ((CollectionPropertyContext) ctx)
              .getElementType() : null;
      boolean shouldSend =
          isOwnerValueProxy || matchesPropertyRef(propertyRefs, propertyName)
              || elementType != null && ValueCodex.canDecode(elementType);

      if (!shouldSend) {
        return false;
      }

      // Call the getter
      Object domainValue = service.getProperty(domainEntity, propertyName);
      if (domainValue == null) {
        return false;
      }

      // Turn the domain object into something usable on the client side
      Type type;
      if (elementType == null) {
        type = ctx.getType();
      } else {
        type = new CollectionType(ctx.getType(), elementType);
      }
      Resolution resolution = resolveClientValue(domainValue, type);
      addPathsToResolution(resolution, propertyName, propertyRefs);
      ctx.set(resolution.getClientObject());
      return false;
    }

    @Override
    public boolean visitValueProperty(String propertyName, Object value, PropertyContext ctx) {
      /*
       * Only call the getter for simple values once since they're not
       * explicitly enumerated.
       */
      if (needsSimpleValues) {
        // Limit unrequested value properties?
        value = service.getProperty(domainEntity, propertyName);
        ctx.set(value);
      }
      return false;
    }
  }

  /**
   * Tracks the state of resolving a single client object.
   */
  private static class Resolution {
    /**
     * There's no Collections shortcut for this.
     */
    private static final SortedSet<String> EMPTY = Collections
        .unmodifiableSortedSet(new TreeSet<String>());

    /**
     * The client object.
     */
    private final Object clientObject;

    /**
     * A one-shot flag for {@link #hasWork()} to ensure that simple properties
     * will be resolved, even when there's no requested property set.
     */
    private boolean needsSimpleValues;
    private SortedSet<String> toResolve = EMPTY;
    private final SortedSet<String> resolved = new TreeSet<String>();
    private final ResolutionKey key;

    public Resolution(Object simpleValue) {
      assert !(simpleValue instanceof Resolution);
      this.clientObject = simpleValue;
      this.key = null;
    }

    public Resolution(ResolutionKey key, BaseProxy clientObject) {
      this.clientObject = clientObject;
      this.key = key;
      needsSimpleValues = true;
    }

    /**
     * Removes the prefix from each requested path and enqueues paths that have
     * not been previously resolved for the next batch of work.
     */
    public void addPaths(String prefix, Collection<String> requestedPaths) {
      // Identity comparison intentional
      if (toResolve == EMPTY) {
        toResolve = new TreeSet<String>();
      }
      prefix = prefix.isEmpty() ? prefix : (prefix + ".");
      int prefixLength = prefix.length();
      for (String path : requestedPaths) {
        if (path.startsWith(prefix)) {
          toResolve.add(path.substring(prefixLength));
        }
      }
      toResolve.removeAll(resolved);
      if (toResolve.isEmpty()) {
        toResolve = EMPTY;
      }
    }

    public Object getClientObject() {
      return clientObject;
    }

    public ResolutionKey getResolutionKey() {
      return key;
    }

    public boolean hasWork() {
      return needsSimpleValues || !toResolve.isEmpty();
    }

    public boolean needsSimpleValues() {
      return needsSimpleValues;
    }

    /**
     * Returns client-object-relative reference paths that should be further
     * resolved.
     */
    public SortedSet<String> takeWork() {
      needsSimpleValues = false;
      SortedSet<String> toReturn = toResolve;
      resolved.addAll(toReturn);
      toResolve = EMPTY;
      return toReturn;
    }
  }

  /**
   * Used to map the objects being resolved and its API slice to the client-side
   * value. This handles the case where a domain object is returned to the
   * client mapped to two proxies of differing types.
   */
  private static class ResolutionKey {
    private final Object domainObject;
    private final int hashCode;
    private final Type requestedType;

    public ResolutionKey(Object domainObject, Type requestedType) {
      this.domainObject = domainObject;
      this.requestedType = requestedType;
      this.hashCode = System.identityHashCode(domainObject) * 13 + requestedType.hashCode() * 7;
    }

    @Override
    public boolean equals(Object o) {
      if (!(o instanceof ResolutionKey)) {
        return false;
      }
      ResolutionKey other = (ResolutionKey) o;
      // Object identity comparison intentional
      if (domainObject != other.domainObject) {
        return false;
      }
      if (!requestedType.equals(other.requestedType)) {
        return false;
      }
      return true;
    }

    public Object getDomainObject() {
      return domainObject;
    }

    @Override
    public int hashCode() {
      return hashCode;
    }

    /**
     * For debugging use only.
     */
    @Override
    public String toString() {
      return domainObject.toString() + " => " + requestedType.toString();
    }
  }

  /**
   * Returns the trailing {@code [n]} index value from a path.
   */
  static int index(String path) {
    int idx = path.lastIndexOf('[');
    if (idx == -1) {
      return -1;
    }
    return Integer.parseInt(path.substring(idx + 1, path.lastIndexOf(']')));
  }

  /**
   * Returns {@code true} if the given prefix is one of the requested property
   * references.
   */
  static boolean matchesPropertyRef(Set<String> propertyRefs, String newPrefix) {
    return propertyRefs.contains(newPrefix.replaceAll("\\[\\d+\\]", ""));
  }

  /**
   * Removes the trailing {@code [n]} from a path.
   */
  static String snipIndex(String path) {
    int idx = path.lastIndexOf('[');
    if (idx == -1) {
      return path;
    }
    return path.substring(0, idx);
  }

  /**
   * Expand the property references in an InvocationMessage into a
   * fully-expanded list of properties. For example, <code>[foo.bar.baz]</code>
   * will be converted into <code>[foo, foo.bar, foo.bar.baz]</code>.
   */
  private static Set<String> expandPropertyRefs(Set<String> refs) {
    if (refs == null) {
      return Collections.emptySet();
    }

    Set<String> toReturn = new TreeSet<String>();
    for (String raw : refs) {
      for (int idx = raw.length(); idx >= 0; idx = raw.lastIndexOf('.', idx - 1)) {
        toReturn.add(raw.substring(0, idx));
      }
    }
    return toReturn;
  }

  /**
   * Maps proxy instances to the Resolution objects.
   */
  private Map<BaseProxy, Resolution> clientObjectsToResolutions =
      new HashMap<BaseProxy, Resolution>();
  /**
   * Maps domain values to client values. This map prevents cycles in the object
   * graph from causing infinite recursion.
   */
  private final Map<ResolutionKey, Resolution> resolved = new HashMap<ResolutionKey, Resolution>();
  private final ServiceLayer service;
  private final RequestState state;
  /**
   * Contains Resolutions with path references that have not yet been resolved.
   */
  private Set<Resolution> toProcess = new LinkedHashSet<Resolution>();
  private int syntheticId;

  /**
   * Should only be called from {@link RequestState}.
   */
  Resolver(RequestState state) {
    this.state = state;
    this.service = state.getServiceLayer();
  }

  /**
   * Given a domain object, return a value that can be encoded by the client.
   * 
   * @param domainValue the domain object to be converted into a client-side
   *          value
   * @param assignableTo the type in the client to which the resolved value
   *          should be assignable. A value of {@code null} indicates that any
   *          resolution will suffice.
   * @param propertyRefs the property references requested by the client
   */
  public Object resolveClientValue(Object domainValue, Type assignableTo, Set<String> propertyRefs) {
    Resolution toReturn = resolveClientValue(domainValue, assignableTo);
    if (toReturn == null) {
      return null;
    }
    addPathsToResolution(toReturn, "", expandPropertyRefs(propertyRefs));
    while (!toProcess.isEmpty()) {
      List<Resolution> working = new ArrayList<Resolution>(toProcess);
      toProcess.clear();
      for (Resolution resolution : working) {
        if (resolution.hasWork()) {
          AutoBean<BaseProxy> bean =
              AutoBeanUtils.getAutoBean((BaseProxy) resolution.getClientObject());
          bean.accept(new PropertyResolver(resolution));
        }
      }
    }
    return toReturn.getClientObject();
  }

  /**
   * Convert a client-side value into a domain value.
   * 
   * @param maybeEntityProxy the client object to resolve
   * @param detectDeadEntities if <code>true</code> this method will throw a
   *          ReportableException containing a {@link DeadEntityException} if an
   *          EntityProxy cannot be resolved
   */
  public Object resolveDomainValue(Object maybeEntityProxy, boolean detectDeadEntities) {
    if (maybeEntityProxy instanceof BaseProxy) {
      AutoBean<BaseProxy> bean = AutoBeanUtils.getAutoBean((BaseProxy) maybeEntityProxy);
      Object domain = bean.getTag(Constants.DOMAIN_OBJECT);
      if (domain == null && detectDeadEntities) {
        throw new ReportableException(new DeadEntityException(
            "The requested entity is not available on the server"));
      }
      return domain;
    } else if (maybeEntityProxy instanceof Collection<?>) {
      Collection<Object> accumulator;
      if (maybeEntityProxy instanceof List<?>) {
        accumulator = new ArrayList<Object>();
      } else if (maybeEntityProxy instanceof Set<?>) {
        accumulator = new HashSet<Object>();
      } else {
        throw new ReportableException("Unsupported collection type "
            + maybeEntityProxy.getClass().getName());
      }
      for (Object o : (Collection<?>) maybeEntityProxy) {
        accumulator.add(resolveDomainValue(o, detectDeadEntities));
      }
      return accumulator;
    }
    return maybeEntityProxy;
  }

  /**
   * Calls {@link Resolution#addPaths(String, Collection)}, enqueuing
   * {@code key} if {@link Resolution#hasWork()} returns {@code true}. This
   * method will also expand paths on the members of Collections.
   */
  private void addPathsToResolution(Resolution resolution, String prefix, Set<String> propertyRefs) {
    if (propertyRefs.isEmpty()) {
      // No work to do
      return;
    }
    if (resolution.getResolutionKey() != null) {
      // Working on a proxied type
      assert resolution.getClientObject() instanceof BaseProxy : "Expecting BaseProxy, found "
          + resolution.getClientObject().getClass().getCanonicalName();
      resolution.addPaths(prefix, propertyRefs);
      if (resolution.hasWork()) {
        toProcess.add(resolution);
      }
      return;
    }
    if (resolution.getClientObject() instanceof Collection) {
      // Pass the paths onto the Resolutions for the contained elements
      Collection<?> collection = (Collection<?>) resolution.getClientObject();
      for (Object obj : collection) {
        Resolution subResolution = clientObjectsToResolutions.get(obj);
        // subResolution will be null for List<Integer>, etc.
        if (subResolution != null) {
          addPathsToResolution(subResolution, prefix, propertyRefs);
        }
      }
      return;
    }
    assert false : "Should not add paths to client type "
        + resolution.getClientObject().getClass().getCanonicalName();
  }

  /**
   * Creates a resolution for a simple value.
   */
  private Resolution makeResolution(Object domainValue) {
    assert !state.isEntityType(domainValue.getClass())
        && !state.isValueType(domainValue.getClass()) : "Not a simple value type";
    return new Resolution(domainValue);
  }

  /**
   * Create or reuse a Resolution for a proxy object.
   */
  private Resolution makeResolution(ResolutionKey key, BaseProxy clientObject) {
    Resolution resolution = resolved.get(key);
    if (resolution == null) {
      resolution = new Resolution(key, clientObject);
      clientObjectsToResolutions.put(clientObject, resolution);
      toProcess.add(resolution);
      resolved.put(key, resolution);
    }
    return resolution;
  }

  /**
   * Creates a proxy instance held by a Resolution for a given domain type.
   */
  private <T extends BaseProxy> Resolution resolveClientProxy(Object domainEntity,
      Class<T> proxyType, ResolutionKey key) {
    if (domainEntity == null) {
      return null;
    }

    SimpleProxyId<? extends BaseProxy> id = state.getStableId(domainEntity);

    boolean isEntityProxy = state.isEntityType(proxyType);
    Object domainVersion;

    // Create the id or update an ephemeral id by calculating its address
    if (id == null || id.isEphemeral()) {
      // The address is an id or an id plus a path
      Object domainId;
      if (isEntityProxy) {
        // Compute data needed to return id to the client
        domainId = service.getId(domainEntity);
        domainVersion = service.getVersion(domainEntity);
      } else {
        domainId = null;
        domainVersion = null;
      }
      if (id == null) {
        if (domainId == null) {
          /*
           * This will happen when server code attempts to return an unpersisted
           * object to the client. In this case, we'll assign a synthetic id
           * that is valid for the duration of the response. The client is
           * expected to assign a client-local id to this object and then it
           * will behave as though it were an object newly-created by the
           * client.
           */
          id = state.getIdFactory().allocateSyntheticId(proxyType, ++syntheticId);
        } else {
          Splittable flatValue = state.flatten(domainId);
          id = state.getIdFactory().getId(proxyType, flatValue.getPayload(), 0);
        }
      } else if (domainId != null) {
        // Mark an ephemeral id as having been persisted
        Splittable flatValue = state.flatten(domainId);
        id.setServerId(flatValue.getPayload());
      }
    } else if (isEntityProxy) {
      // Already have the id, just pull the current version
      domainVersion = service.getVersion(domainEntity);
    } else {
      // The version of a value object is always null
      domainVersion = null;
    }

    @SuppressWarnings("unchecked")
    AutoBean<T> bean = (AutoBean<T>) state.getBeanForPayload(id, domainEntity);
    bean.setTag(Constants.IN_RESPONSE, true);
    if (domainVersion != null) {
      Splittable flatVersion = state.flatten(domainVersion);
      bean.setTag(Constants.VERSION_PROPERTY_B64, SimpleRequestProcessor.toBase64(flatVersion
          .getPayload()));
    }

    T clientObject = bean.as();
    return makeResolution(key, clientObject);
  }

  /**
   * Creates a Resolution object that holds a client value that represents the
   * given domain value. The resolved client value will be assignable to
   * {@code clientType}.
   */
  private Resolution resolveClientValue(Object domainValue, Type clientType) {
    if (domainValue == null) {
      return null;
    }

    boolean anyType = clientType == null;
    if (anyType) {
      clientType = Object.class;
    }

    Class<?> assignableTo = TypeUtils.ensureBaseType(clientType);
    ResolutionKey key = new ResolutionKey(domainValue, clientType);

    Resolution previous = resolved.get(key);
    if (previous != null && assignableTo.isInstance(previous.getClientObject())) {
      return previous;
    }

    Class<?> returnClass = service.resolveClientType(domainValue.getClass(), assignableTo, true);

    if (anyType) {
      assignableTo = returnClass;
    }

    // Pass simple values through
    if (ValueCodex.canDecode(returnClass)) {
      return makeResolution(domainValue);
    }

    // Convert entities to EntityProxies or EntityProxyIds
    boolean isProxy = BaseProxy.class.isAssignableFrom(returnClass);
    boolean isId = EntityProxyId.class.isAssignableFrom(returnClass);
    if (isProxy || isId) {
      Class<? extends BaseProxy> proxyClass = returnClass.asSubclass(BaseProxy.class);
      return resolveClientProxy(domainValue, proxyClass, key);
    }

    // Convert collections
    if (Collection.class.isAssignableFrom(returnClass)) {
      Collection<Object> accumulator;
      if (List.class.isAssignableFrom(returnClass)) {
        accumulator = new ArrayList<Object>();
      } else if (Set.class.isAssignableFrom(returnClass)) {
        accumulator = new HashSet<Object>();
      } else {
        throw new ReportableException("Unsupported collection type" + returnClass.getName());
      }

      Type elementType = TypeUtils.getSingleParameterization(Collection.class, clientType);
      for (Object o : (Collection<?>) domainValue) {
        accumulator.add(resolveClientValue(o, elementType).getClientObject());
      }
      return makeResolution(accumulator);
    }

    throw new ReportableException("Unsupported domain type " + returnClass.getCanonicalName());
  }
}
