/*
 * Copyright 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 java.util;

import static javaemul.internal.InternalPreconditions.checkNotNull;

import jsinterop.annotations.JsNonNull;

/**
 * Skeletal implementation of the Map interface. <a
 * href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/AbstractMap.html">[Sun
 * docs]</a>
 *
 * @param <K> the key type.
 * @param <V> the value type.
 */
public abstract class AbstractMap<K, V> implements Map<K, V> {

  /**
   * A mutable {@link Map.Entry} shared by several {@link Map} implementations.
   */
  public static class SimpleEntry<K, V> extends AbstractEntry<K, V> {
    public SimpleEntry(K key, V value) {
      super(key, value);
    }

    public SimpleEntry(Entry<? extends K, ? extends V> entry) {
      super(entry.getKey(), entry.getValue());
    }
  }

  /**
   * An immutable {@link Map.Entry} shared by several {@link Map} implementations.
   */
  public static class SimpleImmutableEntry<K, V> extends AbstractEntry<K, V> {
    public SimpleImmutableEntry(K key, V value) {
      super(key, value);
    }

    public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) {
      super(entry.getKey(), entry.getValue());
    }

    @Override
    public V setValue(V value) {
      throw new UnsupportedOperationException();
    }
  }

  /**
   * Basic {@link Map.Entry} implementation used by {@link SimpleEntry}
   * and {@link SimpleImmutableEntry}.
   */
  private abstract static class AbstractEntry<K, V> implements Entry<K, V> {
    private final K key;
    private V value;

    protected AbstractEntry(K key, V value) {
      this.key = key;
      this.value = value;
    }

    @Override
    public K getKey() {
      return key;
    }

    @Override
    public V getValue() {
      return value;
    }

    @Override
    public V setValue(V value) {
      V oldValue = this.value;
      this.value = value;
      return oldValue;
    }

    @Override
    public boolean equals(Object other) {
      if (!(other instanceof Entry)) {
        return false;
      }
      Entry<?, ?> entry = (Entry<?, ?>) other;
      return Objects.equals(key, entry.getKey())
          && Objects.equals(value, entry.getValue());
    }

    /**
     * Calculate the hash code using Sun's specified algorithm.
     */
    @Override
    public int hashCode() {
      return Objects.hashCode(key) ^ Objects.hashCode(value);
    }

    @Override
    public String toString() {
      // for compatibility with the real Jre: issue 3422
      return key + "=" + value;
    }
  }

  protected AbstractMap() {
  }

  @Override
  public void clear() {
    entrySet().clear();
  }

  @Override
  public boolean containsKey(Object key) {
    return implFindEntry(key, false) != null;
  }

  @Override
  public boolean containsValue(Object value) {
    for (Entry<K, V> entry : entrySet()) {
      V v = entry.getValue();
      if (Objects.equals(value, v)) {
        return true;
      }
    }
    return false;
  }

  boolean containsEntry(Entry<?, ?> entry) {
    Object key = entry.getKey();
    Object value = entry.getValue();
    Object ourValue = get(key);

    if (!Objects.equals(value, ourValue)) {
      return false;
    }

    // Perhaps it was null and we don't contain the key?
    if (ourValue == null && !containsKey(key)) {
      return false;
    }

    return true;
  }

  @Override
  public boolean equals(Object obj) {
    if (obj == this) {
      return true;
    }
    if (!(obj instanceof Map)) {
      return false;
    }
    Map<?, ?> otherMap = (Map<?, ?>) obj;
    if (size() != otherMap.size()) {
      return false;
    }

    for (Entry<?, ?> entry : otherMap.entrySet()) {
      if (!containsEntry(entry)) {
        return false;
      }
    }
    return true;
  }

  @Override
  public V get(Object key) {
    return getEntryValueOrNull(implFindEntry(key, false));
  }

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

  @Override
  public boolean isEmpty() {
    return size() == 0;
  }

  @Override
  @JsNonNull
  public Set<K> keySet() {
    return new AbstractSet<K>() {
      @Override
      public void clear() {
        AbstractMap.this.clear();
      }

      @Override
      public boolean contains(Object key) {
        return containsKey(key);
      }

      @Override
      public Iterator<K> iterator() {
        final Iterator<Entry<K, V>> outerIter = entrySet().iterator();
        return new Iterator<K>() {
          @Override
          public boolean hasNext() {
            return outerIter.hasNext();
          }

          @Override
          public K next() {
            Entry<K, V> entry = outerIter.next();
            return entry.getKey();
          }

          @Override
          public void remove() {
            outerIter.remove();
          }
        };
      }

      @Override
      public boolean remove(Object key) {
        if (containsKey(key)) {
          AbstractMap.this.remove(key);
          return true;
        }
        return false;
      }

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

  @Override
  public V put(K key, V value) {
    throw new UnsupportedOperationException("Put not supported on this map");
  }

  @Override
  public void putAll(Map<? extends K, ? extends V> map) {
    checkNotNull(map);
    for (Entry<? extends K, ? extends V> e : map.entrySet()) {
      put(e.getKey(), e.getValue());
    }
  }

  @Override
  public V remove(Object key) {
    return getEntryValueOrNull(implFindEntry(key, true));
  }

  @Override
  public int size() {
    return entrySet().size();
  }

  @Override
  public String toString() {
    StringJoiner joiner = new StringJoiner(", ", "{", "}");
    for (Entry<K, V> entry : entrySet()) {
      joiner.add(toString(entry));
    }
    return joiner.toString();
  }

  private String toString(Entry<K, V> entry) {
    return toString(entry.getKey()) + "=" + toString(entry.getValue());
  }

  private String toString(Object o) {
    return o == this ? "(this Map)" : String.valueOf(o);
  }

  @Override
  public Collection<V> values() {
    return new AbstractCollection<V>() {
      @Override
      public void clear() {
        AbstractMap.this.clear();
      }

      @Override
      public boolean contains(Object value) {
        return containsValue(value);
      }

      @Override
      public Iterator<V> iterator() {
        final Iterator<Entry<K, V>> outerIter = entrySet().iterator();
        return new Iterator<V>() {
          @Override
          public boolean hasNext() {
            return outerIter.hasNext();
          }

          @Override
          public V next() {
            Entry<K, V> entry = outerIter.next();
            return entry.getValue();
          }

          @Override
          public void remove() {
            outerIter.remove();
          }
        };
      }

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

  static <K, V> K getEntryKeyOrNull(Entry<K, V> entry) {
    return entry == null ? null : entry.getKey();
  }

  static <K, V> V getEntryValueOrNull(Entry<K, V> entry) {
    return entry == null ? null : entry.getValue();
  }

  private Entry<K, V> implFindEntry(Object key, boolean remove) {
    for (Iterator<Entry<K, V>> iter = entrySet().iterator(); iter.hasNext();) {
      Entry<K, V> entry = iter.next();
      K k = entry.getKey();
      if (Objects.equals(key, k)) {
        if (remove) {
          entry = new SimpleEntry<K, V>(entry.getKey(), entry.getValue());
          iter.remove();
        }
        return entry;
      }
    }
    return null;
  }
}
