/*
 * Copyright (C) 2007 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.inject.internal;

import static com.google.inject.internal.ReferenceType.STRONG;
import static com.google.common.base.Preconditions.checkNotNull;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.ref.Reference;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Concurrent hash map that wraps keys and/or values in soft or weak references.
 * Does not support null keys or values. Uses identity equality for weak and
 * soft keys.
 *
 * <p>The concurrent semantics of {@link ConcurrentHashMap} combined with the
 * fact that the garbage collector can asynchronously reclaim and clean up
 * keys and values at any time can lead to some racy semantics. For example,
 * {@link #size()} returns an upper bound on the size; that is, the actual size
 * may be smaller in cases where the key or value has been reclaimed but the map
 * entry has not been cleaned up yet.
 *
 * @author crazybob@google.com (Bob Lee)
 * @author fry@google.com (Charles Fry)
 */
@SuppressWarnings("unchecked")
public class ReferenceMap<K, V> extends AbstractMap<K, V>
    implements ConcurrentMap<K, V>, Serializable {

  transient ConcurrentMap<Object, Object> delegate;

  private final ReferenceType keyReferenceType;
  private final ReferenceType valueReferenceType;

  /**
   * Concurrent hash map that wraps keys and/or values based on specified
   * reference types.
   *
   * @param keyReferenceType key reference type
   * @param valueReferenceType value reference type
   */
  public ReferenceMap(
      ReferenceType keyReferenceType, ReferenceType valueReferenceType) {
    ensureNotNull(keyReferenceType, valueReferenceType);

    if (keyReferenceType == ReferenceType.PHANTOM
        || valueReferenceType == ReferenceType.PHANTOM) {
      throw new IllegalArgumentException("Phantom references not supported.");
    }

    this.delegate = new ConcurrentHashMap<Object, Object>();
    this.keyReferenceType = keyReferenceType;
    this.valueReferenceType = valueReferenceType;
  }

  V internalGet(K key) {
    Object valueReference = delegate.get(makeKeyReferenceAware(key));
    return dereferenceValue(valueReference);
  }

  public V get(final Object key) {
    checkNotNull(key, "key");
    return internalGet((K) key);
  }

  private V execute(Strategy strategy, K key, V value) {
    ensureNotNull(key, value);
    Object keyReference = referenceKey(key);
    return (V) strategy.execute(
        this, keyReference, referenceValue(keyReference, value)
    );
  }

  public V put(K key, V value) {
    return execute(putStrategy(), key, value);
  }

  public V remove(Object key) {
    checkNotNull(key, "key");
    Object referenceAwareKey = makeKeyReferenceAware(key);
    Object valueReference = delegate.remove(referenceAwareKey);
    return dereferenceValue(valueReference);
  }

  public int size() {
    return delegate.size();
  }

  public boolean isEmpty() {
    return delegate.isEmpty();
  }

  public boolean containsKey(Object key) {
    checkNotNull(key, "key");
    Object referenceAwareKey = makeKeyReferenceAware(key);
    return delegate.containsKey(referenceAwareKey);
  }

  public boolean containsValue(Object value) {
    checkNotNull(value, "value");
    for (Object valueReference : delegate.values()) {
      if (value.equals(dereferenceValue(valueReference))) {
        return true;
      }
    }
    return false;
  }

  public void putAll(Map<? extends K, ? extends V> t) {
    for (Map.Entry<? extends K, ? extends V> entry : t.entrySet()) {
      put(entry.getKey(), entry.getValue());
    }
  }

  public void clear() {
    delegate.clear();
  }

  public V putIfAbsent(K key, V value) {
    return execute(putIfAbsentStrategy(), key, value);
  }

  public boolean remove(Object key, Object value) {
    ensureNotNull(key, value);
    Object referenceAwareKey = makeKeyReferenceAware(key);
    Object referenceAwareValue = makeValueReferenceAware(value);
    return delegate.remove(referenceAwareKey, referenceAwareValue);
  }

  public boolean replace(K key, V oldValue, V newValue) {
    ensureNotNull(key, oldValue, newValue);
    Object keyReference = referenceKey(key);

    Object referenceAwareOldValue = makeValueReferenceAware(oldValue);
    return delegate.replace(keyReference, referenceAwareOldValue,
        referenceValue(keyReference, newValue)
    );
  }

  public V replace(K key, V value) {
    return execute(replaceStrategy(), key, value);
  }

  private transient volatile Set<Map.Entry<K, V>> entrySet = null;

  public Set<Map.Entry<K, V>> entrySet() {
    if (entrySet == null) {
      entrySet = new EntrySet();
    }
    return entrySet;
  }

  /** Dereferences an entry. Returns null if the key or value has been gc'ed. */
  private Entry dereferenceEntry(Map.Entry<Object, Object> entry) {
    K key = dereferenceKey(entry.getKey());
    V value = dereferenceValue(entry.getValue());
    return (key == null || value == null)
        ? null
        : new Entry(key, value);
  }

  /** Creates a reference for a key. */
  Object referenceKey(K key) {
    switch (keyReferenceType) {
      case STRONG:
        return key;
      case SOFT:
        return new SoftKeyReference(key);
      case WEAK:
        return new WeakKeyReference(key);
      default:
        throw new AssertionError();
    }
  }

  /** Converts a reference to a key. */
  private K dereferenceKey(Object o) {
    return (K) dereference(keyReferenceType, o);
  }

  /** Converts a reference to a value. */
  V dereferenceValue(Object o) {
    if (o == null) {
      return null;
    }
    Object value = dereference(valueReferenceType, o);
    if (o instanceof InternalReference) {
      InternalReference ref = (InternalReference) o;
      if (value == null) {
        // old value was garbage collected
        ref.finalizeReferent();
      }
    }
    return (V) value;
  }

  /** Returns the refererent for reference given its reference type. */
  private Object dereference(ReferenceType referenceType, Object reference) {
    return referenceType == STRONG ? reference : ((Reference) reference).get();
  }

  /** Creates a reference for a value. */
  Object referenceValue(Object keyReference, Object value) {
    switch (valueReferenceType) {
      case STRONG:
        return value;
      case SOFT:
        return new SoftValueReference(keyReference, value);
      case WEAK:
        return new WeakValueReference(keyReference, value);
      default:
        throw new AssertionError();
    }
  }

  /**
   * Wraps key so it can be compared to a referenced key for equality.
   */
  private Object makeKeyReferenceAware(Object o) {
    return keyReferenceType == STRONG ? o : new KeyReferenceAwareWrapper(o);
  }

  /** Wraps value so it can be compared to a referenced value for equality. */
  private Object makeValueReferenceAware(Object o) {
    return valueReferenceType == STRONG ? o : new ReferenceAwareWrapper(o);
  }

  /**
   * Marker interface to differentiate external and internal references. Also
   * duplicates FinalizableReference and Reference.get for internal use.
   */
  interface InternalReference {
    void finalizeReferent();

    Object get();
  }

  private static int keyHashCode(Object key) {
    return System.identityHashCode(key);
  }

  /*
   * Tests weak and soft references for identity equality. Compares references
   * to other references and wrappers. If o is a reference, this returns true if
   * r == o or if r and o reference the same non-null object. If o is a wrapper,
   * this returns true if r's referent is identical to the wrapped object.
   */
  private static boolean referenceEquals(Reference r, Object o) {
    // compare reference to reference.
    if (o instanceof InternalReference) {
      // are they the same reference? used in cleanup.
      if (o == r) {
        return true;
      }

      // do they reference identical values? used in conditional puts.
      Object referent = ((Reference) o).get();
      return referent != null && referent == r.get();
    }

    // is the wrapped object identical to the referent? used in lookups.
    return ((ReferenceAwareWrapper) o).unwrap() == r.get();
  }

  /**
   * Returns {@code true} if the specified value reference has been garbage
   * collected. The value behind the reference is also passed in, rather than
   * queried inside this method, to ensure that the return statement of this
   * method will still hold true after it has returned (that is, a value
   * reference exists outside of this method which will prevent that value from
   * being garbage collected).
   *
   * @param valueReference the value reference to be tested
   * @param value the object referenced by {@code valueReference}
   * @return {@code true} if {@code valueReference} is non-null and {@code
   *     value} is null
   */
  private static boolean isExpired(Object valueReference, Object value) {
    return (valueReference != null) && (value == null);
  }

  /**
   * Big hack. Used to compare keys and values to referenced keys and values
   * without creating more references.
   */
  static class ReferenceAwareWrapper {
    final Object wrapped;

    ReferenceAwareWrapper(Object wrapped) {
      this.wrapped = wrapped;
    }

    Object unwrap() {
      return wrapped;
    }

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

    @Override public boolean equals(Object obj) {
      // defer to reference's equals() logic.
      return obj.equals(this);
    }
  }

  /** Used for keys. Overrides hash code to use identity hash code. */
  static class KeyReferenceAwareWrapper extends ReferenceAwareWrapper {
    public KeyReferenceAwareWrapper(Object wrapped) {
      super(wrapped);
    }

    public int hashCode() {
      return System.identityHashCode(wrapped);
    }
  }

  class SoftKeyReference extends FinalizableSoftReference<Object>
      implements InternalReference {
    final int hashCode;

    public SoftKeyReference(Object key) {
      super(key);
      this.hashCode = keyHashCode(key);
    }

    public void finalizeReferent() {
      delegate.remove(this);
    }

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

    @Override public boolean equals(Object o) {
      return referenceEquals(this, o);
    }
  }

  class WeakKeyReference extends FinalizableWeakReference<Object>
      implements InternalReference {
    final int hashCode;

    public WeakKeyReference(Object key) {
      super(key);
      this.hashCode = keyHashCode(key);
    }

    public void finalizeReferent() {
      delegate.remove(this);
    }

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

    @Override public boolean equals(Object o) {
      return referenceEquals(this, o);
    }
  }

  class SoftValueReference extends FinalizableSoftReference<Object>
      implements InternalReference {
    final Object keyReference;

    public SoftValueReference(Object keyReference, Object value) {
      super(value);
      this.keyReference = keyReference;
    }

    public void finalizeReferent() {
      delegate.remove(keyReference, this);
    }

    @Override public boolean equals(Object obj) {
      return referenceEquals(this, obj);
    }
  }

  class WeakValueReference extends FinalizableWeakReference<Object>
      implements InternalReference {
    final Object keyReference;

    public WeakValueReference(Object keyReference, Object value) {
      super(value);
      this.keyReference = keyReference;
    }

    public void finalizeReferent() {
      delegate.remove(keyReference, this);
    }

    @Override public boolean equals(Object obj) {
      return referenceEquals(this, obj);
    }
  }

  protected interface Strategy {
    public Object execute(
        ReferenceMap map, Object keyReference, Object valueReference);
  }

  // TODO(crazybob): a getter called put() is probably a bad idea
  protected Strategy putStrategy() {
    return PutStrategy.PUT;
  }

  protected Strategy putIfAbsentStrategy() {
    return PutStrategy.PUT_IF_ABSENT;
  }

  protected Strategy replaceStrategy() {
    return PutStrategy.REPLACE;
  }

  private enum PutStrategy implements Strategy {
    PUT {
      public Object execute(
          ReferenceMap map, Object keyReference, Object valueReference) {
        return map.dereferenceValue(
            map.delegate.put(keyReference, valueReference));
      }
    },

    REPLACE {
      public Object execute(
          ReferenceMap map, Object keyReference, Object valueReference) {
        // ensure that the existing value is not collected
        do {
          Object existingValueReference;
          Object existingValue;
          do {
            existingValueReference = map.delegate.get(keyReference);
            existingValue = map.dereferenceValue(existingValueReference);
          } while (isExpired(existingValueReference, existingValue));

          if (existingValueReference == null) {
            // nothing to replace
            return false;
          }

          if (map.delegate.replace(
              keyReference, existingValueReference, valueReference)) {
            // existingValue didn't expire since we still have a reference to it
            return existingValue;
          }
        } while (true);
      }
    },

    PUT_IF_ABSENT {
      public Object execute(
          ReferenceMap map, Object keyReference, Object valueReference) {
        Object existingValueReference;
        Object existingValue;
        do {
          existingValueReference
              = map.delegate.putIfAbsent(keyReference, valueReference);
          existingValue = map.dereferenceValue(existingValueReference);
        } while (isExpired(existingValueReference, existingValue));
        return existingValue;
      }
    },
  }

  private static PutStrategy defaultPutStrategy;

  protected PutStrategy getPutStrategy() {
    return defaultPutStrategy;
  }

  class Entry implements Map.Entry<K, V> {
    final K key;
    V value;

    public Entry(K key, V value) {
      this.key = key;
      this.value = value;
    }

    public K getKey() {
      return this.key;
    }

    public V getValue() {
      return this.value;
    }

    public V setValue(V newValue) {
      value = newValue;
      return put(key, newValue);
    }

    public int hashCode() {
      return key.hashCode() * 31 + value.hashCode();
    }

    public boolean equals(Object o) {
      if (!(o instanceof ReferenceMap.Entry)) {
        return false;
      }

      Entry entry = (Entry) o;
      return key.equals(entry.key) && value.equals(entry.value);
    }

    public String toString() {
      return key + "=" + value;
    }
  }

  private class ReferenceIterator implements Iterator<Map.Entry<K, V>> {
    private Iterator<Map.Entry<Object, Object>> i =
        delegate.entrySet().iterator();
    private Map.Entry<K, V> nextEntry;
    private Map.Entry<K, V> lastReturned;

    public ReferenceIterator() {
      advance();
    }

    private void advance() {
      while (i.hasNext()) {
        Map.Entry<K, V> entry = dereferenceEntry(i.next());
        if (entry != null) {
          nextEntry = entry;
          return;
        }
      }

      // nothing left
      nextEntry = null;
    }

    public boolean hasNext() {
      return nextEntry != null;
    }

    public Map.Entry<K, V> next() {
      if (nextEntry == null) {
        throw new NoSuchElementException();
      }
      lastReturned = nextEntry;
      advance();
      return lastReturned;
    }

    public void remove() {
      ReferenceMap.this.remove(lastReturned.getKey());
    }
  }

  private class EntrySet extends AbstractSet<Map.Entry<K, V>> {
    public Iterator<Map.Entry<K, V>> iterator() {
      return new ReferenceIterator();
    }

    public int size() {
      return delegate.size();
    }

    public boolean contains(Object o) {
      if (!(o instanceof Map.Entry)) {
        return false;
      }
      Map.Entry<K, V> e = (Map.Entry<K, V>) o;
      V v = ReferenceMap.this.get(e.getKey());
      return v != null && v.equals(e.getValue());
    }

    public boolean remove(Object o) {
      if (!(o instanceof Map.Entry)) {
        return false;
      }
      Map.Entry<K, V> e = (Map.Entry<K, V>) o;
      return ReferenceMap.this.remove(e.getKey(), e.getValue());
    }

    public void clear() {
      delegate.clear();
    }
  }

  static void ensureNotNull(Object... array) {
    for (int i = 0; i < array.length; i++) {
      if (array[i] == null) {
        throw new NullPointerException("Argument #" + i + " is null.");
      }
    }
  }

  private void writeObject(ObjectOutputStream out) throws IOException {
    out.defaultWriteObject();
    out.writeInt(size());
    for (Map.Entry<Object, Object> entry : delegate.entrySet()) {
      Object key = dereferenceKey(entry.getKey());
      Object value = dereferenceValue(entry.getValue());

      // don't persist gc'ed entries.
      if (key != null && value != null) {
        out.writeObject(key);
        out.writeObject(value);
      }
    }
    out.writeObject(null);
  }

  private void readObject(ObjectInputStream in)
      throws IOException, ClassNotFoundException {
    in.defaultReadObject();
    int size = in.readInt();
    this.delegate = new ConcurrentHashMap<Object, Object>(size);
    while (true) {
      K key = (K) in.readObject();
      if (key == null) {
        break;
      }
      V value = (V) in.readObject();
      put(key, value);
    }
  }

  private static final long serialVersionUID = 0;
}
