// Copyright (c) 2015, 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.

/// Defines [LookupMap], a simple map that can be optimized by dart2js.
library lookup_map;

/// [LookupMap] is a simple, but very restricted map.  The map can only hold
/// constant keys and the only way to use the map is to retrieve values with a
/// key you already have.  Except for lookup, any other operation in [Map] (like
/// forEach, keys, values, length, etc) is not available.
///
/// Constant [LookupMap]s are understood by dart2js and can be tree-shaken
/// internally: if a key is not used elsewhere in the program, its entry can be
/// deleted from the map during compilation without changing the program's
/// behavior. Currently dart2js supports tree-shaking keys that are `Type`
/// literals, and any const expression that can only be created with a const
/// constructor. This means that primitives, Strings, and constant objects that
/// override the `==` operator cannot be tree-shaken.
///
/// Note: [LookupMap] is unlikely going to be useful for individual developers
/// writing code by hand. It is mainly intended as a helper utility for
/// frameworks that need to autogenerate data and associate it with a type in
/// the program. For example, this can be used by a dependency injection system
/// to record how to create instances of a given type. A dependency injection
/// framework can store in a [LookupMap] all the information it needs for every
/// injectable type in every library and package.  When compiling a specific
/// application, dart2js can tree-shake the data of types that are not used by
/// the application. Similarly, this can also be used by
/// serialization/deserialization packages that can store in a [LookupMap] the
/// deserialization logic for a given type.
class LookupMap<K, V> {
  /// The key for [LookupMap]s with a single key/value pair.
  final K _key;

  /// The value for [LookupMap]s with a single key/value pair.
  final V _value;

  /// List of alternating key-value pairs in the map.
  final List _entries;

  /// Other maps to which this map delegates lookup operations if the key is not
  /// found on [entries]. See [LookupMap]'s constructor for details.
  final List<LookupMap<K, V>> _nestedMaps;

  /// Creates a lookup-map given a list of key-value pair [entries], and
  /// optionally additional entries from other [LookupMap]s.
  ///
  /// When doing a lookup, if the key is not found on [entries]. The lookup will
  /// be performed in reverse order of the list of [nestedMaps], so a later
  /// entry for a key shadows previous entries.  For example, in:
  ///
  ///     const map = const LookupMap(const [A, 1],
  ///         const [const LookupMap(const [A, 2, B, 4]),
  ///                const LookupMap(const [A, 3, B, 5]));
  ///
  /// `map[A]` returns `1` and `map[B]` returns `5`.
  ///
  /// Note: in the future we expect to change [entries] to be a const map
  /// instead of a list of key-value pairs.
  // TODO(sigmund): make entries a map once we fix TypeImpl.== (issue #17207).
  const LookupMap(List entries, [List<LookupMap<K, V>> nestedMaps = const []])
      : _key = null,
        _value = null,
        _entries = entries,
        _nestedMaps = nestedMaps;

  /// Creates a lookup map with a single key-value pair.
  const LookupMap.pair(K key, V value)
      : _key = key,
        _value = value,
        _entries = const [],
        _nestedMaps = const [];

  /// Return the data corresponding to [key].
  V operator [](K key) {
    var map = _flatMap[this];
    if (map == null) {
      map = {};
      _addEntriesTo(map);
      _flatMap[this] = map;
    }
    return map[key];
  }

  /// Add to [map] entries from [nestedMaps] and from [entries] according to the
  /// precedense order described in [nestedMaps].
  _addEntriesTo(Map map) {
    _nestedMaps.forEach((m) => m._addEntriesTo(map));
    for (var i = 0; i < _entries.length; i += 2) {
      map[_entries[i]] = _entries[i + 1];
    }
    if (_key != null) map[_key] = _value;
  }
}

/// An expando that stores a flatten version of a [LookupMap], this is
/// computed and stored the first time the map is accessed.
final _flatMap = new Expando('_flat_map');

/// Internal constant that matches the version in the pubspec. This is used by
/// dart2js to ensure that optimizations are only enabled on known versions of
/// this code.
// Note: this needs to be kept in sync with the pubspec, otherwise
// test/version_check_test would fail.
final _version = '0.0.1+1';
