// 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";

/// An insertion-ordered [Map] with expected constant-time lookup.
///
/// A non-constant map literal, like `{"a": 42, "b": 7}`, is a `LinkedHashMap`.
///
/// The [keys], [values] and [entries] are iterated in key insertion order.
///
/// The map uses a hash-table to look up entries, so keys must have
/// suitable implementations of [Object.operator==] and [Object.hashCode].
/// If the hash codes are not well-distributed, the performance of map
/// operations may suffer.
///
/// The insertion order of keys is remembered,
/// and keys are iterated in the order they were inserted into the map.
/// Values and entries are iterated in their corresponding key's order.
/// Changing a key's value, when the key is already in the map,
/// does not change the iteration order,
/// but removing the key and adding it again
/// will make it be last in the iteration order.
///
/// **Notice:**
/// Do not modify a map (add or remove keys) while an operation
/// is being performed on that map, for example in functions
/// called during a [forEach] or [putIfAbsent] call,
/// or while iterating the map ([keys], [values] or [entries]).
///
/// The keys of a `LinkedHashMap` 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 `==`.
///
/// Example:
///
/// ```dart
/// final planetsByDiameter = {0.949: 'Venus'}; // A new LinkedHashMap
/// ```
/// To add data to a map, use [operator[]=], [addAll] or [addEntries].
/// ```dart continued
/// planetsByDiameter[1] = 'Earth';
/// planetsByDiameter.addAll({0.532: 'Mars', 11.209: 'Jupiter'});
/// ```
/// To check if the map is empty, use [isEmpty] or [isNotEmpty].
/// To find the number of map entries, use [length].
/// ```dart continued
/// print(planetsByDiameter.isEmpty); // false
/// print(planetsByDiameter.length); // 4
/// print(planetsByDiameter);
/// // {0.949: Venus, 1.0: Earth, 0.532: Mars, 11.209: Jupiter}
/// ```
/// The [forEach] method calls a function for each key/value entry of the map.
/// ```dart continued
/// planetsByDiameter.forEach((key, value) {
///   print('$key \t $value');
///   // 0.949    Venus
///   // 1.0      Earth
///   // 0.532    Mars
///   // 11.209   Jupiter
/// });
/// ```
/// To check whether the map has an entry with a specific key, use [containsKey].
/// ```dart continued
/// final keyOneExists = planetsByDiameter.containsKey(1); // true
/// final keyFiveExists = planetsByDiameter.containsKey(5); // false
/// ```
/// To check whether the map has an entry with a specific value,
/// use [containsValue].
/// ```dart continued
/// final earthExists = planetsByDiameter.containsValue('Earth'); // true
/// final saturnExists =  planetsByDiameter.containsValue('Saturn'); // false
/// ```
/// To remove an entry with a specific key, use [remove].
/// ```dart continued
/// final removedValue = planetsByDiameter.remove(1);
/// print(removedValue); // Earth
/// print(planetsByDiameter); // {0.949: Venus, 0.532: Mars, 11.209: Jupiter}
/// ```
/// To remove multiple entries at the same time, based on their keys and values,
/// use [removeWhere].
/// ```dart continued
/// planetsByDiameter.removeWhere((key, value) => key == 0.949);
/// print(planetsByDiameter); // {0.532: Mars, 11.209: Jupiter}
/// ```
/// To conditionally add or modify a value for a specific key, depending on
/// whether there already is an entry with that key,
/// use [putIfAbsent] or [update].
/// ```dart continued
/// planetsByDiameter.update(0.949, (v) => 'Venus', ifAbsent: () => 'Venus');
/// planetsByDiameter.putIfAbsent(0.532, () => "Another Mars if needed");
/// print(planetsByDiameter); // {0.532: Mars, 11.209: Jupiter, 0.949: Venus}
/// ```
/// To update the values of all keys, based on the existing key and value,
/// use [updateAll].
/// ```dart continued
/// planetsByDiameter.updateAll((key, value) => 'X');
/// print(planetsByDiameter); // {0.532: X, 11.209: X, 0.949: X}
/// ```
/// To remove all entries and empty the map, use [clear].
/// ```dart continued
/// planetsByDiameter.clear();
/// print(planetsByDiameter); // {}
/// print(planetsByDiameter.isEmpty); // true
/// ```
/// **See also:**
/// * [Map], the general interface of key/value pair collections.
/// * [HashMap] is unordered (the order of iteration is not guaranteed).
/// * [SplayTreeMap] iterates the keys in sorted order.
abstract final class LinkedHashMap<K, V> implements Map<K, V> {
  /// Creates an insertion-ordered hash-table based [Map].
  ///
  /// 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.
  /// The [equals] function *must not* change the map it's used as an equality
  /// for. If it does, the resulting behavior is unspecified.
  ///
  /// Similarly, 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.
  /// The [hashCode] function *must not* change the map it's used as a hash code
  /// for. If it does, the resulting behavior is unspecified.
  ///
  /// The used `equals` and `hashCode` methods 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 in the table. If the hash code or equality of an object does
  /// change, the resulting behavior is unspecified.
  ///
  /// If you supply one of [equals] or [hashCode],
  /// you should generally also supply the other.
  ///
  /// Some [equals] or [hashCode] functions might not work for all objects.
  /// If [isValidKey] is supplied, it's used to check a potential key
  /// which is not necessarily an instance of [K], like the arguments to
  /// [operator []], [remove] and [containsKey], which are typed as `Object?`.
  /// If [isValidKey] returns `false`, for an object, the [equals] and
  /// [hashCode] functions are not called, and no key equal to that object
  /// is assumed to be in the map.
  /// The [isValidKey] function defaults to just testing if the object is an
  /// instance of [K].
  ///
  /// Example:
  /// ```dart template:expression
  /// LikedHashMap<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 precisely `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 [LinkedHashMap.identity].
  external factory LinkedHashMap({
    bool Function(K, K)? equals,
    int Function(K)? hashCode,
    bool Function(dynamic)? isValidKey,
  });

  /// Creates an insertion-ordered identity-based map.
  ///
  /// Effectively shorthand for:
  /// ```dart template:expression
  /// LinkedHashMap<K, V>(equals: identical,
  ///                     hashCode: identityHashCode)
  /// ```
  external factory LinkedHashMap.identity();

  /// Creates a [LinkedHashMap] that contains all key value pairs of [other].
  ///
  /// The keys must all be instances of [K] and the values to [V].
  /// The [other] map itself can have any type.
  /// Example:
  /// ```dart
  /// final baseMap = <num, Object>{1: 'A', 2: 'B', 3: 'C'};
  /// final fromBaseMap = LinkedHashMap<int, String>.from(baseMap);
  /// print(fromBaseMap); // {1: A, 2: B, 3: C}
  /// ```
  factory LinkedHashMap.from(Map<dynamic, dynamic> other) {
    LinkedHashMap<K, V> result = LinkedHashMap<K, V>();
    other.forEach((dynamic k, dynamic v) {
      result[k as K] = v as V;
    });
    return result;
  }

  /// Creates a [LinkedHashMap] that contains all key value pairs of [other].
  /// Example:
  /// ```dart
  /// final baseMap = <int, String>{3: 'A', 2: 'B', 1: 'C', 4: 'D'};
  /// final mapOf = LinkedHashMap<num, Object>.of(baseMap);
  /// print(mapOf); // {3: A, 2: B, 1: C, 4: D}
  /// ```
  factory LinkedHashMap.of(Map<K, V> other) =>
      LinkedHashMap<K, V>()..addAll(other);

  /// Creates a [LinkedHashMap] 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
  /// both default to the identity function.
  /// Example:
  /// ```dart
  /// final numbers = [11, 12, 13, 14];
  /// final mapFromIterable =
  ///     LinkedHashMap.fromIterable(numbers, key: (i) => i, value: (i) => i * i);
  /// print(mapFromIterable); // {11: 121, 12: 144, 13: 169, 14: 196}
  /// ```
  factory LinkedHashMap.fromIterable(
    Iterable iterable, {
    K Function(dynamic element)? key,
    V Function(dynamic element)? value,
  }) {
    LinkedHashMap<K, V> map = LinkedHashMap<K, V>();
    MapBase._fillMapWithMappedIterable(map, iterable, key, value);
    return map;
  }

  /// Creates a [LinkedHashMap] 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.
  /// Example:
  /// ```dart
  /// final values = [0.06, 0.81, 1, 0.11];
  /// final keys = ['Mercury', 'Venus', 'Earth', 'Mars'];
  /// final mapFromIterables = LinkedHashMap.fromIterables(keys, values);
  /// print(mapFromIterables);
  /// // {Mercury: 0.06, Venus: 0.81, Earth: 1, Mars: 0.11}
  /// ```
  factory LinkedHashMap.fromIterables(Iterable<K> keys, Iterable<V> values) {
    LinkedHashMap<K, V> map = LinkedHashMap<K, V>();
    MapBase._fillMapWithIterables(map, keys, values);
    return map;
  }

  /// Creates a [LinkedHashMap] containing the entries of [entries].
  ///
  /// Returns a new `LinkedHashMap<K, V>` where all entries of [entries]
  /// have been added in iteration order.
  ///
  /// If multiple [entries] have the same key,
  /// later occurrences overwrite the earlier ones.
  /// Example:
  /// ```dart
  /// final numbers = [11, 12, 13, 14];
  /// final map = LinkedHashMap.fromEntries(numbers.map((i) => MapEntry(i, i * i)));
  /// print(map); // {11: 121, 12: 144, 13: 169, 14: 196}
  /// ```
  factory LinkedHashMap.fromEntries(Iterable<MapEntry<K, V>> entries) =>
      LinkedHashMap<K, V>()..addEntries(entries);
}
