// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of dart.collection;

/** Default function for equality comparison in customized HashMaps */
bool _defaultEquals(a, b) => a == b;
/** Default function for hash-code computation in customized HashMaps */
int _defaultHashCode(a) => a.hashCode;

/** Type of custom equality function */
typedef bool _Equality<K>(K a, K b);
/** Type of custom hash code function. */
typedef int _Hasher<K>(K object);

/**
 * A hash-table based implementation of [Map].
 *
 * The keys of a `HashMap` must have consistent [Object.==]
 * and [Object.hashCode] implementations. This means that the `==` operator
 * must define a stable equivalence relation on the keys (reflexive,
 * symmetric, transitive, and consistent over time), and that `hashCode`
 * must be the same for objects that are considered equal by `==`.
 *
 * The map allows `null` as a key.
 *
 * Iterating the map's keys, values or entries (through [forEach])
 * may happen in any order.
 * The iteration order only changes when the map is modified.
 * Values are iterated in the same order as their associated keys,
 * so iterating the [keys] and [values] in parallel
 * will give matching key and value pairs.
 */
abstract class HashMap<K, V> implements Map<K, V> {
  /**
   * Creates an unordered hash-table based [Map].
   *
   * The created map is not ordered in any way. When iterating the keys or
   * values, the iteration order is unspecified except that it will stay the
   * same as long as the map isn't changed.
   *
   * If [equals] is provided, it is used to compare the keys in the table with
   * new keys. If [equals] is omitted, the key's own [Object.==] is used
   * instead.
   *
   * Similar, if [hashCode] is provided, it is used to produce a hash value
   * for keys in order to place them in the hash table. If it is omitted, the
   * key's own [Object.hashCode] is used.
   *
   * If using methods like [[]], [remove] and [containsKey] together
   * with a custom equality and hashcode, an extra `isValidKey` function
   * can be supplied. This function is called before calling [equals] or
   * [hashCode] with an argument that may not be a [K] instance, and if the
   * call returns false, the key is assumed to not be in the set.
   * The [isValidKey] function defaults to just testing if the object is a
   * [K] instance.
   *
   * Example:
   *
   *     new HashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
   *                          hashCode: (int e) => e % 5)
   *
   * This example map does not need an `isValidKey` function to be passed.
   * The default function accepts only `int` values, which can safely be
   * passed to both the `equals` and `hashCode` functions.
   *
   * If neither `equals`, `hashCode`, nor `isValidKey` is provided,
   * the default `isValidKey` instead accepts all keys.
   * The default equality and hashcode operations are assumed to work on all
   * objects.
   *
   * Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
   * and `isValidKey` is omitted, the resulting map is identity based,
   * and the `isValidKey` defaults to accepting all keys.
   * Such a map can be created directly using [HashMap.identity].
   *
   * The used `equals` and `hashCode` method should always be consistent,
   * so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
   * of an object, or what it compares equal to, should not change while the
   * object is a key in the map. If it does change, the result is unpredictable.
   *
   * If you supply one of [equals] and [hashCode],
   * you should generally also to supply the other.
   */
  external factory HashMap(
      {bool equals(K key1, K key2),
      int hashCode(K key),
      bool isValidKey(potentialKey)});

  /**
   * Creates an unordered identity-based map.
   *
   * Effectively a shorthand for:
   *
   *     new HashMap<K, V>(equals: identical,
   *                       hashCode: identityHashCode)
   */
  external factory HashMap.identity();

  /**
   * Creates a [HashMap] that contains all key/value pairs of [other].
   */
  factory HashMap.from(Map other) {
    HashMap<K, V> result = new HashMap<K, V>();
    other.forEach((k, v) {
      result[k] = v;
    });
    return result;
  }

  /**
   * Creates a [HashMap] where the keys and values are computed from the
   * [iterable].
   *
   * For each element of the [iterable] this constructor computes a key/value
   * pair, by applying [key] and [value] respectively.
   *
   * The keys of the key/value pairs do not need to be unique. The last
   * occurrence of a key will simply overwrite any previous value.
   *
   * If no values are specified for [key] and [value] the default is the
   * identity function.
   */
  factory HashMap.fromIterable(Iterable iterable,
      {K key(element), V value(element)}) {
    HashMap<K, V> map = new HashMap<K, V>();
    Maps._fillMapWithMappedIterable(map, iterable, key, value);
    return map;
  }

  /**
   * Creates a [HashMap] associating the given [keys] to [values].
   *
   * This constructor iterates over [keys] and [values] and maps each element of
   * [keys] to the corresponding element of [values].
   *
   * If [keys] contains the same object multiple times, the last occurrence
   * overwrites the previous value.
   *
   * It is an error if the two [Iterable]s don't have the same length.
   */
  factory HashMap.fromIterables(Iterable<K> keys, Iterable<V> values) {
    HashMap<K, V> map = new HashMap<K, V>();
    Maps._fillMapWithIterables(map, keys, values);
    return map;
  }
}
