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

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 {
  /// An empty observable map that never has changes.
  static const ObservableMap EMPTY = const _ObservableUnmodifiableMap(const {});

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

  /// Create a new unmodifiable map from [map].
  ///
  /// [ObservableMap.changes] always returns an empty stream, and mutating or
  /// adding change records throws an [UnsupportedError].
  factory ObservableMap.unmodifiable(Map<K, V> map) {
    if (map is! UnmodifiableMapView<K, V>) {
      map = new Map<K, V>.unmodifiable(map);
    }
    return new _ObservableUnmodifiableMap(map);
  }
}

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();
  }
}

class _ObservableUnmodifiableMap<K, V> extends DelegatingMap<K, V>
    implements ObservableMap<K, V> {
  const _ObservableUnmodifiableMap(Map<K, V> map) : super(map);

  @override
  Stream<List<ChangeRecord>> get changes => const Stream.empty();

  @override
  bool deliverChanges() => false;

  // TODO: implement hasObservers
  @override
  final bool hasObservers = false;

  @override
  void notifyChange([ChangeRecord change]) {
    throw new UnsupportedError('Not modifiable');
  }

  @override
  /*=T*/ notifyPropertyChange/*<T>*/(
    Symbol field,
    /*=T*/
    oldValue,
    /*=T*/
    newValue,
  ) {
    throw new UnsupportedError('Not modifiable');
  }

  @override
  void observed() {}

  @override
  void unobserved() {}
}
