// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:collection';

import '../value_observer.dart';
import 'converted_change.dart';

/// Sledge DataTypes internal storage.
class KeyValueStorage<K, V> extends MapBase<K, V> with MapMixin<K, V> {
  final Map<K, V> _storage;
  // [_changesToRollback] stores the ConvertedChange that should be applied to
  // roll back the transaction that is in progress. For each key that was
  // affected in this transaction:
  // - it stores the key and the old value in [changedKeys], if key was in [_storage]
  // - it stores the key in [deletedKeys], if key wasn't in [_storage]
  final ConvertedChange<K, V> _changeToRollback;
  ValueObserver _observer;

  /// Creates a storage using the provided [equals] as equality.
  KeyValueStorage({bool equals(K key1, K key2), int hashCode(K key)})
      : _storage = new HashMap<K, V>(equals: equals, hashCode: hashCode),
        _changeToRollback = new ConvertedChange(
            new HashMap<K, V>(equals: equals, hashCode: hashCode),
            new HashSet<K>(equals: equals, hashCode: hashCode));

  @override
  V operator [](Object key) => _storage[key];

  @override
  void operator []=(K key, V value) {
    _backupStateOfKeyValue(key);
    _storage[key] = value;
    _valueWasChanged();
  }

  @override
  V remove(Object key) {
    _backupStateOfKeyValue(key);
    V result = this[key];
    _storage.remove(key);
    _valueWasChanged();
    return result;
  }

  @override
  void clear() {
    _storage.keys.forEach(_backupStateOfKeyValue);
    _storage.clear();
    _valueWasChanged();
  }

  @override
  Iterable<K> get keys => _storage.keys;

  @override
  int get length => _storage.length;

  /// Retrieves the current transaction's data.
  ConvertedChange<K, V> getChange() {
    final change = new ConvertedChange<K, V>();
    // [_changeToRollback.deletedKeys] is a collection of keys that were not in
    // [_storage] when the transaction started, but were affected by this
    // transaction.
    for (final key in _changeToRollback.deletedKeys) {
      // When we add a key-value pair in a transaction, we add the corresponding
      // key in [_changeToRollback.deletedKeys]. It is valid however, to remove
      // that key in the same transaction. In that case, [deletedKeys] will not
      // be updated (to remove the key), and _storage will not contain the given
      // value. We thus need to check whether the key exists, and only add it in
      // the list of [change.changedEntries] if it does.
      if (_storage.containsKey(key)) {
        change.changedEntries[key] = _storage[key];
      }
    }
    // [_changeToRollback.changedEntries] is a collection of keys that were in
    // [_storage] when transaction started and were affected by this transaction.
    for (final key in _changeToRollback.changedEntries.keys) {
      final newValue = _storage[key];
      if (newValue != null) {
        change.changedEntries[key] = newValue;
      } else {
        change.deletedKeys.add(key);
      }
    }
    return change;
  }

  /// Completes the current transaction and starts the next one.
  void completeTransaction() {
    _changeToRollback.clear();
  }

  /// Applies external transaction.
  void applyChange(ConvertedChange<K, V> change) {
    _storage.addAll(change.changedEntries);
    change.deletedKeys.forEach(_storage.remove);
  }

  /// Rolls back all local modifications.
  void rollbackChange() {
    applyChange(_changeToRollback);
    _changeToRollback.clear();
  }

  /// Sets the observer.
  set observer(ValueObserver observer) {
    _observer = observer;
  }

  /// Backs up info for [key] to enable rollback on it.
  void _backupStateOfKeyValue(K key) {
    if (_changeToRollback.deletedKeys.contains(key) ||
        _changeToRollback.changedEntries.containsKey(key)) {
      return;
    }
    final previousValue = this[key];
    if (previousValue == null) {
      _changeToRollback.deletedKeys.add(key);
    } else {
      _changeToRollback.changedEntries[key] = previousValue;
    }
  }

  void _valueWasChanged() {
    _observer?.valueWasChanged();
  }
}
