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

import com.google.gwt.core.client.impl.WeakMapping;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Utility methods for working with AutoBeans.
 */
public final class AutoBeanUtils {
  /*
   * TODO(bobv): Make Comparison a real type that holds a map contain the diff
   * between the two objects. Then export a Map of PendingComparison to
   * Comparisons as a public API to make it easy for developers to perform deep
   * diffs across a graph structure.
   * 
   * Three-way merge...
   */

  private enum Comparison {
    TRUE, FALSE, PENDING;
  }

  /**
   * A Pair where order does not matter and the objects are compared by
   * identity.
   */
  private static class PendingComparison {
    private final AutoBean<?> a;
    private final AutoBean<?> b;
    private final int hashCode;

    public PendingComparison(AutoBean<?> a, AutoBean<?> b) {
      this.a = a;
      this.b = b;
      // Don't make relatively prime since order does not matter
      hashCode = System.identityHashCode(a) + System.identityHashCode(b);
    }

    @Override
    public boolean equals(Object o) {
      if (!(o instanceof PendingComparison)) {
        return false;
      }
      PendingComparison other = (PendingComparison) o;
      return a == other.a && b == other.b || // Direct match
          a == other.b && b == other.a; // Swapped
    }

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

  /**
   * Compare two graphs of AutoBeans based on values.
   * <p>
   * <ul>
   * <li>AutoBeans are compared based on type and property values</li>
   * <li>Lists are compared with element-order equality</li>
   * <li>Sets and all other Collection types are compare with bag equality</li>
   * <li>Maps are compared as a lists of keys-value pairs</li>
   * <li>{@link Splittable Splittables} are compared by value</li>
   * </ul>
   * <p>
   * This will work for both simple and wrapper AutoBeans.
   * <p>
   * This method may crawl the entire object graph reachable from the input
   * parameters and may be arbitrarily expensive to compute.
   * 
   * @param a an {@link AutoBean}
   * @param b an {@link AutoBean}
   * @return {@code false} if any values in the graph reachable through
   *         <code>a</code> are different from those reachable from
   *         <code>b</code>
   */
  public static boolean deepEquals(AutoBean<?> a, AutoBean<?> b) {
    return sameOrEquals(a, b, new HashMap<PendingComparison, Comparison>());
  }

  /**
   * Returns a map of properties that differ (via {@link Object#equals(Object)})
   * between two AutoBeans. The keys are property names and the values are the
   * value of the property in <code>b</code>. Properties present in
   * <code>a</code> but missing in <code>b</code> will be represented by
   * <code>null</code> values. This implementation will compare AutoBeans of
   * different parameterizations, although the diff produced is likely
   * meaningless.
   * <p>
   * This will work for both simple and wrapper AutoBeans.
   * 
   * @param a an {@link AutoBean}
   * @param b an {@link AutoBean}
   * @return a {@link Map} of differing properties
   */
  public static Map<String, Object> diff(AutoBean<?> a, AutoBean<?> b) {
    // Fast check for comparing an object to itself
    if (a.equals(b)) {
      return Collections.emptyMap();
    }
    final Map<String, Object> toReturn = getAllProperties(b);

    // Remove the entries that are equal, adding nulls for missing properties
    a.accept(new AutoBeanVisitor() {
      @Override
      public boolean visitReferenceProperty(String propertyName, AutoBean<?> previousValue,
          PropertyContext ctx) {
        if (toReturn.containsKey(propertyName)) {
          if (equal(propertyName, previousValue)) {
            // No change
            toReturn.remove(propertyName);
          }
        } else {
          // The predecessor has a value that this object doesn't.
          toReturn.put(propertyName, null);
        }
        return false;
      }

      @Override
      public boolean visitValueProperty(String propertyName, Object previousValue,
          PropertyContext ctx) {
        if (toReturn.containsKey(propertyName)) {
          if (equal(propertyName, previousValue)) {
            // No change
            toReturn.remove(propertyName);
          }
        } else {
          // The predecessor has a value that this object doesn't.
          toReturn.put(propertyName, null);
        }
        return false;
      }

      private boolean equal(String propertyName, AutoBean<?> previousValue) {
        return previousValue == null && toReturn.get(propertyName) == null || previousValue != null
            && equal(propertyName, previousValue.as());
      }

      private boolean equal(String propertyName, Object previousValue) {
        Object currentValue = toReturn.get(propertyName);
        return previousValue == null && currentValue == null || previousValue != null
            && previousValue.equals(currentValue);
      }
    });
    return toReturn;
  }

  /**
   * Returns a map that is a copy of the properties contained in an AutoBean.
   * The returned map is mutable, but editing it will not have any effect on the
   * bean that produced it.
   * 
   * @param bean an {@link AutoBean}
   * @return a {@link Map} of the bean's properties
   */
  public static Map<String, Object> getAllProperties(AutoBean<?> bean) {
    final Map<String, Object> toReturn = new LinkedHashMap<String, Object>();

    // Look at the previous value of all properties
    bean.accept(new AutoBeanVisitor() {
      @Override
      public boolean visitReferenceProperty(String propertyName, AutoBean<?> value,
          PropertyContext ctx) {
        toReturn.put(propertyName, value == null ? null : value.as());
        return false;
      }

      @Override
      public boolean visitValueProperty(String propertyName, Object value, PropertyContext ctx) {
        toReturn.put(propertyName, value);
        return false;
      }
    });
    return toReturn;
  }

  /**
   * Return the single AutoBean wrapper that is observing the delegate object or
   * {@code null} if the parameter is {@code null}or not wrapped by an AutoBean.
   * 
   * @param delegate a delegate object, or {@code null}
   * @return the {@link AutoBean} wrapper for the delegate, or {@code null}
   */
  @SuppressWarnings("unchecked")
  public static <T, U extends T> AutoBean<T> getAutoBean(U delegate) {
    return delegate == null ? null : (AutoBean<T>) WeakMapping.get(delegate, AutoBean.class
        .getName());
  }

  /**
   * Compare two AutoBeans, this method has the type fan-out.
   */
  static boolean sameOrEquals(Object value, Object otherValue,
      Map<PendingComparison, Comparison> pending) {
    if (value == otherValue) {
      // Fast exit
      return true;
    }

    if (value instanceof Collection<?> && otherValue instanceof Collection<?>) {
      // Check collections
      return sameOrEquals((Collection<?>) value, (Collection<?>) otherValue, pending, null);
    }

    if (value instanceof Map<?, ?> && otherValue instanceof Map<?, ?>) {
      // Check maps
      return sameOrEquals((Map<?, ?>) value, (Map<?, ?>) otherValue, pending);
    }

    if (value instanceof Splittable && otherValue instanceof Splittable) {
      return sameOrEquals((Splittable) value, (Splittable) otherValue, pending);
    }

    // Possibly substitute the AutoBean for its shim
    {
      AutoBean<?> maybeValue = AutoBeanUtils.getAutoBean(value);
      AutoBean<?> maybeOther = AutoBeanUtils.getAutoBean(otherValue);
      if (maybeValue != null && maybeOther != null) {
        value = maybeValue;
        otherValue = maybeOther;
      }
    }

    if (value instanceof AutoBean<?> && otherValue instanceof AutoBean<?>) {
      // Check ValueProxies
      return sameOrEquals((AutoBean<?>) value, (AutoBean<?>) otherValue, pending);
    }

    if (value == null ^ otherValue == null) {
      // One is null, the other isn't
      return false;
    }

    if (value != null && !value.equals(otherValue)) {
      // Regular object equality
      return false;
    }
    return true;
  }

  /**
   * If a comparison between two AutoBeans is currently pending, this method
   * will skip their comparison.
   */
  private static boolean sameOrEquals(AutoBean<?> value, AutoBean<?> otherValue,
      Map<PendingComparison, Comparison> pending) {
    if (value == otherValue) {
      // Simple case
      return true;
    } else if (!value.getType().equals(otherValue.getType())) {
      // Beans of different types
      return false;
    }

    /*
     * The PendingComparison key allows us to break reference cycles when
     * crawling the graph. Since the entire operation is essentially a
     * concatenated && operation, it's ok to speculatively return true for
     * repeated a.equals(b) tests.
     */
    PendingComparison key = new PendingComparison(value, otherValue);
    Comparison previous = pending.get(key);
    if (previous == null) {
      // Prevent the same comparison from being made
      pending.put(key, Comparison.PENDING);

      // Compare each property
      Map<String, Object> beanProperties = AutoBeanUtils.getAllProperties(value);
      Map<String, Object> otherProperties = AutoBeanUtils.getAllProperties(otherValue);
      for (Map.Entry<String, Object> entry : beanProperties.entrySet()) {
        Object property = entry.getValue();
        Object otherProperty = otherProperties.get(entry.getKey());
        if (!sameOrEquals(property, otherProperty, pending)) {
          pending.put(key, Comparison.FALSE);
          return false;
        }
      }
      pending.put(key, Comparison.TRUE);
      return true;
    } else {
      // Return true for TRUE or PENDING
      return !Comparison.FALSE.equals(previous);
    }
  }

  /**
   * Compare two collections by size, then by contents. List comparisons will
   * preserve order. All other collections will be treated with bag semantics.
   */
  private static boolean sameOrEquals(Collection<?> collection, Collection<?> otherCollection,
      Map<PendingComparison, Comparison> pending, Map<Object, Object> pairs) {
    if (collection.size() != otherCollection.size()) {
      return false;
    }

    if (collection instanceof List<?>) {
      // Lists we can simply iterate over
      Iterator<?> it = collection.iterator();
      Iterator<?> otherIt = otherCollection.iterator();
      while (it.hasNext()) {
        assert otherIt.hasNext();
        Object element = it.next();
        Object otherElement = otherIt.next();
        if (!sameOrEquals(element, otherElement, pending)) {
          return false;
        }
        if (pairs != null) {
          pairs.put(element, otherElement);
        }
      }
    } else {
      // Do an n*m comparison on any other collection type
      List<Object> values = new ArrayList<Object>(collection);
      List<Object> otherValues = new ArrayList<Object>(otherCollection);
      it : for (Iterator<Object> it = values.iterator(); it.hasNext();) {
        Object value = it.next();
        for (Iterator<Object> otherIt = otherValues.iterator(); otherIt.hasNext();) {
          Object otherValue = otherIt.next();
          if (sameOrEquals(value, otherValue, pending)) {
            if (pairs != null) {
              pairs.put(value, otherValue);
            }
            // If a match is found, remove both values from their lists
            it.remove();
            otherIt.remove();
            continue it;
          }
        }
        // A match for the value wasn't found
        return false;
      }
      assert values.isEmpty() && otherValues.isEmpty();
    }
    return true;
  }

  /**
   * Compare two Maps by size, and key-value pairs.
   */
  private static boolean sameOrEquals(Map<?, ?> map, Map<?, ?> otherMap,
      Map<PendingComparison, Comparison> pending) {
    if (map.size() != otherMap.size()) {
      return false;
    }
    Map<Object, Object> pairs = new IdentityHashMap<Object, Object>();
    if (!sameOrEquals(map.keySet(), otherMap.keySet(), pending, pairs)) {
      return false;
    }
    for (Map.Entry<?, ?> entry : map.entrySet()) {
      Object otherValue = otherMap.get(pairs.get(entry.getKey()));
      if (!sameOrEquals(entry.getValue(), otherValue, pending)) {
        return false;
      }
    }
    return true;
  }

  /**
   * Compare Splittables by kind and values.
   */
  private static boolean sameOrEquals(Splittable value, Splittable otherValue,
      Map<PendingComparison, Comparison> pending) {
    if (value == otherValue) {
      return true;
    }

    // Strings
    if (value.isString()) {
      if (!otherValue.isString()) {
        return false;
      }
      return value.asString().equals(otherValue.asString());
    }

    // Arrays
    if (value.isIndexed()) {
      if (!otherValue.isIndexed()) {
        return false;
      }

      if (value.size() != otherValue.size()) {
        return false;
      }

      for (int i = 0, j = value.size(); i < j; i++) {
        if (!sameOrEquals(value.get(i), otherValue.get(i), pending)) {
          return false;
        }
      }
      return true;
    }

    // Objects
    if (value.isKeyed()) {
      if (!otherValue.isKeyed()) {
        return false;
      }
      /*
       * We want to treat a missing property key as a null value, so we can't
       * just compare the key lists.
       */
      List<String> keys = value.getPropertyKeys();
      for (String key : keys) {
        if (value.isNull(key)) {
          // If value['foo'] is null, other['foo'] must also be null
          if (!otherValue.isNull(key)) {
            return false;
          }
        } else if (otherValue.isNull(key)
            || !sameOrEquals(value.get(key), otherValue.get(key), pending)) {
          return false;
        }
      }

      // Look at keys only in otherValue, and ensure nullness
      List<String> otherKeys = new ArrayList<String>(otherValue.getPropertyKeys());
      otherKeys.removeAll(keys);
      for (String key : otherKeys) {
        if (!value.isNull(key)) {
          return false;
        }
      }
      return true;
    }

    // Unexpected
    throw new UnsupportedOperationException("Splittable of unknown type");
  }

  /**
   * Utility class.
   */
  private AutoBeanUtils() {
  }
}
