import 'dart:async';
import 'dart:collection';

import 'package:collection/collection.dart';
import 'package:observable/observable.dart';

/// A [Map] that broadcasts [changes] to subscribers for efficient mutations.
///
/// When client code expects a read heavy/write light workload, it is often more
/// efficient to notify _when_ something has changed, instead of constantly
/// diffing lists to find a single change (like an updated key-value). You may
/// accept an observable map to be notified of mutations:
///     ```
///     set grades(Map<String, int> grades) {
///       buildBook(grades);
///       if (names is ObservableMap<String>, int) {
///         grades.changes.listen(updateBook);
///       }
///     }
///     ```
///
/// *See [MapDiffer] to manually diff two lists instead*
abstract class ObservableMap<K, V> implements Map<K, V>, Observable {
  /// Creates a new observable map.
  factory ObservableMap() {
    return new _ObservableDelegatingMap(new HashMap<K, V>());
  }

  /// Like [ObservableMap.from], but creates an empty type.
  factory ObservableMap.createFromType(Map<K, V> other) {
    ObservableMap<K, V> result;
    if (other is LinkedHashMap) {
      result = new ObservableMap<K, V>.linked();
    } else if (other is SplayTreeMap) {
      result = new ObservableMap<K, V>.sorted();
    } else {
      result = new ObservableMap<K, V>();
    }
    return result;
  }

  /// Create a new observable map using [map] as a backing store.
  factory ObservableMap.delegate(Map<K, V> map) {
    return new _ObservableDelegatingMap<K, V>(map);
  }

  /// Creates a new observable map that contains all entries in [other].
  ///
  /// It will attempt to use the same backing map  type if the other map is
  /// either a [LinkedHashMap], [SplayTreeMap], or [HashMap]. Otherwise it will
  /// fall back to using a [HashMap].
  factory ObservableMap.from(Map<K, V> other) {
    return new ObservableMap<K, V>.createFromType(other)..addAll(other);
  }

  /// Creates a new observable map using a [LinkedHashMap].
  factory ObservableMap.linked() {
    return new _ObservableDelegatingMap<K, V>(new LinkedHashMap<K, V>());
  }

  /// Creates a new observable map using a [SplayTreeMap].
  factory ObservableMap.sorted() {
    return new _ObservableDelegatingMap<K, V>(new SplayTreeMap<K, V>());
  }

  /// Creates a new observable map wrapping [other].
  @Deprecated('Use ObservableMap.delegate for API consistency')
  factory ObservableMap.spy(Map<K, V> other) = ObservableMap<K, V>.delegate;
}

class _ObservableDelegatingMap<K, V> extends DelegatingMap<K, V>
    implements ObservableMap<K, V> {
  final _allChanges = new ChangeNotifier();

  _ObservableDelegatingMap(Map<K, V> map) : super(map);

  // Observable

  @override
  Stream<List<ChangeRecord>> get changes => _allChanges.changes;

  // ChangeNotifier (deprecated for ObservableMap)

  @override
  bool deliverChanges() => _allChanges.deliverChanges();

  @override
  bool get hasObservers => _allChanges.hasObservers;

  @override
  void notifyChange([ChangeRecord change]) {
    _allChanges.notifyChange(change);
  }

  @override
  /*=T*/ notifyPropertyChange/*<T>*/(
    Symbol field,
    /*=T*/
    oldValue,
    /*=T*/
    newValue,
  ) {
    if (oldValue != newValue) {
      _allChanges.notifyChange(
        new PropertyChangeRecord/*<T>*/(this, field, oldValue, newValue),
      );
    }
    return newValue;
  }

  @override
  void observed() {}

  @override
  void unobserved() {}

  @override
  operator []=(K key, V newValue) {
    if (!hasObservers) {
      super[key] = newValue;
      return;
    }

    final oldLength = super.length;
    V oldValue = super[key];
    super[key] = newValue;

    if (oldLength != length) {
      notifyPropertyChange(#length, oldLength, length);
      notifyChange(new MapChangeRecord<K, V>.insert(key, newValue));
    } else {
      notifyChange(new MapChangeRecord<K, V>(key, oldValue, newValue));
    }
  }

  @override
  void addAll(Map<K, V> other) {
    if (!hasObservers) {
      super.addAll(other);
      return;
    }

    other.forEach((k, v) => this[k] = v);
  }

  @override
  V putIfAbsent(K key, V ifAbsent()) {
    final oldLength = length;
    final result = super.putIfAbsent(key, ifAbsent);
    if (hasObservers && oldLength != length) {
      notifyPropertyChange(#length, oldLength, length);
      notifyChange(new MapChangeRecord<K, V>.insert(key, result));
    }
    return result;
  }

  @override
  V remove(Object key) {
    final oldLength = length;
    final result = super.remove(key);
    if (hasObservers && oldLength != length) {
      notifyChange(new MapChangeRecord<K, V>.remove(key as K, result));
      notifyPropertyChange(#length, oldLength, length);
    }
    return result;
  }

  @override
  void clear() {
    if (!hasObservers || isEmpty) {
      super.clear();
      return;
    }
    final oldLength = length;
    forEach((k, v) {
      notifyChange(new MapChangeRecord<K, V>.remove(k, v));
    });
    notifyPropertyChange(#length, oldLength, 0);
    super.clear();
  }
}
