// Copyright (c) 2015, Google Inc. 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 built_collection.map;

/// The Built Collection builder for [BuiltMap].
///
/// It implements the mutating part of the [Map] interface.
///
/// See the
/// [Built Collection library documentation](#built_collection/built_collection)
/// for the general properties of Built Collections.
class MapBuilder<K, V> {
  /// Used by [_createMap] to instantiate [_map]. The default value is `null`.
  _MapFactory<K, V> _mapFactory;
  Map<K, V> _map;
  _BuiltMap<K, V> _mapOwner;

  /// Instantiates with elements from a [Map] or [BuiltMap].
  ///
  /// Must be called with a generic type parameter.
  ///
  /// Wrong: `new MapBuilder({1: '1', 2: '2', 3: '3'})`.
  ///
  /// Right: `new MapBuilder<int, String>({1: '1', 2: '2', 3: '3'})`,
  ///
  /// Rejects nulls. Rejects keys and values of the wrong type.
  factory MapBuilder([map = const {}]) {
    return new MapBuilder<K, V>._uninitialized()..replace(map);
  }

  /// Converts to a [BuiltMap].
  ///
  /// The `MapBuilder` can be modified again and used to create any number
  /// of `BuiltMap`s.
  BuiltMap<K, V> build() {
    if (_mapOwner == null) {
      _mapOwner = new _BuiltMap<K, V>.withSafeMap(_mapFactory, _map);
    }
    return _mapOwner;
  }

  /// Applies a function to `this`.
  void update(updates(MapBuilder<K, V> builder)) {
    updates(this);
  }

  /// Replaces all elements with elements from a [Map] or [BuiltMap].
  void replace(Object map) {
    if (map is _BuiltMap<K, V> && map._mapFactory == _mapFactory) {
      _setOwner(map);
    } else if (map is BuiltMap) {
      final replacement = _createMap();
      map.forEach((Object key, Object value) {
        replacement[key as K] = value as V;
      });
      _setSafeMap(replacement);
    } else if (map is Map) {
      final replacement = _createMap();
      map.forEach((Object key, Object value) {
        replacement[key as K] = value as V;
      });
      _setSafeMap(replacement);
    } else {
      throw new ArgumentError(
          'expected Map or BuiltMap, got ${map.runtimeType}');
    }
  }

  /// Uses `base` as the collection type for all maps created by this builder.
  ///
  ///     // Iterates over elements in ascending order.
  ///     new MapBuilder<int, String>()
  ///       ..withBase(() => new SplayTreeMap<int, String>());
  ///
  ///     // Uses custom equality.
  ///     new MapBuilder<int, String>()
  ///       ..withBase(() => new LinkedHashMap<int, String>(
  ///           equals: (int a, int b) => a % 255 == b % 255,
  ///           hashCode: (int n) => (n % 255).hashCode));
  ///
  /// The map returned by `base` must be empty, mutable, and each call must
  /// instantiate and return a new object.
  ///
  /// Use [withDefaultBase] to reset `base` to the default value.
  void withBase(_MapFactory<K, V> base) {
    if (base == null) {
      throw new ArgumentError.notNull('base');
    }
    _mapFactory = base;
    _setSafeMap(_createMap()..addAll(_map));
  }

  /// As [withBase], but sets `base` back to the default value, which
  /// instantiates `Map<K, V>`.
  void withDefaultBase() {
    _mapFactory = null;
    _setSafeMap(_createMap()..addAll(_map));
  }

  /// As [Map.fromIterable] but adds.
  ///
  /// [key] and [value] default to the identity function.
  void addIterable<T>(Iterable<T> iterable,
      {K key(T element), V value(T element)}) {
    if (key == null) key = (T x) => x as K;
    if (value == null) value = (T x) => x as V;
    for (final element in iterable) {
      this[key(element)] = value(element);
    }
  }

  // Based on Map.

  /// As [Map].
  V operator [](Object key) => _map[key];

  /// As [Map].
  void operator []=(K key, V value) {
    _checkKey(key);
    _checkValue(value);
    _safeMap[key] = value;
  }

  /// As [Map.length].
  int get length => _map.length;

  /// As [Map.isEmpty].
  bool get isEmpty => _map.isEmpty;

  /// As [Map.isNotEmpty].
  bool get isNotEmpty => _map.isNotEmpty;

  /// As [Map.putIfAbsent].
  V putIfAbsent(K key, V ifAbsent()) {
    _checkKey(key);
    return _safeMap.putIfAbsent(key, () {
      final value = ifAbsent();
      _checkValue(value);
      return value;
    });
  }

  /// As [Map.addAll].
  void addAll(Map<K, V> other) {
    _checkKeys(other.keys);
    _checkValues(other.values);
    _safeMap.addAll(other);
  }

  /// As [Map.remove].
  V remove(Object key) => _safeMap.remove(key);

  /// As [Map.removeWhere].
  void removeWhere(bool predicate(K key, V value)) {
    _safeMap.removeWhere(predicate);
  }

  /// As [Map.clear].
  void clear() {
    _safeMap.clear();
  }

  /// As [Map.addEntries].
  void addEntries(Iterable<MapEntry<K, V>> newEntries) {
    _safeMap.addEntries(newEntries);
  }

  /// As [Map.update].
  V updateValue(K key, V update(V value), {V ifAbsent()}) =>
      _safeMap.update(key, update, ifAbsent: ifAbsent);

  /// As [Map.updateAll].
  void updateAllValues(V update(K key, V value)) {
    _safeMap.updateAll(update);
  }

  // Internal.

  MapBuilder._uninitialized() {
    _checkGenericTypeParameter();
  }

  MapBuilder._fromBuiltMap(_BuiltMap<K, V> map)
      : _mapFactory = map._mapFactory,
        _map = map._map,
        _mapOwner = map;

  void _setOwner(_BuiltMap<K, V> mapOwner) {
    assert(mapOwner._mapFactory == _mapFactory,
        "Can't reuse a built map that uses a different base");
    _mapOwner = mapOwner;
    _map = mapOwner._map;
  }

  void _setSafeMap(Map<K, V> map) {
    _mapOwner = null;
    _map = map;
  }

  Map<K, V> get _safeMap {
    if (_mapOwner != null) {
      _map = _createMap()..addAll(_map);
      _mapOwner = null;
    }
    return _map;
  }

  Map<K, V> _createMap() =>
      _mapFactory != null ? _mapFactory() : new Map<K, V>();

  void _checkGenericTypeParameter() {
    if (K == dynamic) {
      throw new UnsupportedError(
          'explicit key type required, for example "new MapBuilder<int, int>"');
    }
    if (V == dynamic) {
      throw new UnsupportedError('explicit value type required, '
          'for example "new MapBuilder<int, int>"');
    }
  }

  void _checkKey(K key) {
    if (identical(key, null)) {
      throw new ArgumentError('null key');
    }
  }

  void _checkKeys(Iterable keys) {
    for (final key in keys) {
      if (key is! K) {
        throw new ArgumentError('invalid key: $key');
      }
    }
  }

  void _checkValue(V value) {
    if (identical(value, null)) {
      throw new ArgumentError('null value');
    }
  }

  void _checkValues(Iterable values) {
    for (final value in values) {
      if (value is! V) {
        throw new ArgumentError('invalid value: $value');
      }
    }
  }
}
