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

// This file is hand-formatted.

import 'dart:async';
import 'dart:convert';

import '../dart/model.dart';

/// Signature for the callback passed to [DynamicContent.subscribe].
typedef SubscriptionCallback = void Function(Object value);

/// Returns a copy of a data structure if it consists of only [DynamicMap]s,
/// [DynamicList]s, [int]s, [double]s, [bool]s, and [String]s.
///
/// This is relatively expensive as the entire data structure must be walked and
/// new objects created.
Object? deepClone(Object? template) {
  if (template == null) {
    return null;
  } else if (template is DynamicMap) {
    return template.map((String key, Object? value) => MapEntry<String, Object?>(key, deepClone(value)));
  } else if (template is DynamicList) {
    return template.map((Object? value) => deepClone(value)).toList();
  } else {
    assert(template is int || template is double || template is bool || template is String, 'unexpected state object type: ${template.runtimeType} ($template)');
    return template;
  }
}

/// Configuration data from the remote widgets.
///
/// Typically this represents the data model, and is updated frequently (or at
/// least, more frequently than the remote widget definitions) by the server
/// (or, indeed, by local code, in response to events or other activity).
///
/// ## Structure
///
/// A [DynamicContent] object represents a tree. A consumer (the remote widgets)
/// can subscribe to a node to obtain its value.
///
/// The root of a [DynamicContent] tree is a map of string-value pairs. The
/// values are:
///
///  * Other maps of string-value pairs ([DynamicMap]).
///  * Lists of values ([DynamicList]).
///  * Booleans ([bool]).
///  * Integers ([int]).
///  * Doubles ([double]).
///  * Strings ([String]).
///
/// The keys in the root map are independently updated. Typically each
/// represents a different category of data from the server that the server
/// updates independently, e.g. theming information and the app state might be
/// provided separately.
///
/// ## Updates
///
/// Data is updated using [update] and [updateAll]. The objects passed to those
/// methods are of the types described above.
///
/// Objects for [update] can be obtained in several ways:
///
/// 1. Dart maps, lists, and literals of the types given above ("raw data") can
///    be created directly in code. This is useful for configuring remote
///    widgets with local client information such as the current time, GPS
///    coordinates, system settings like dark mode, window dimensions, etc,
///    where the data was never encoded in the first place.
///
/// 2. A Remote Flutter Widgets binary data blob can be parsed using
///    [decodeDataBlob]. This is the preferred method for decoding data obtained
///    from the network. See [encodeDataBlob] for a function that generates data
///    in this format.
///
/// 3. A Remote Flutter Widgets text data file can be parsed using
///    [parseTextDataFile]. Decoding this text format is about ten times slower
///    than decoding the binary format and about five times slower than decoding
///    JSON, so it is discouraged in production applications. This text
///    representation of the Remote Flutter Widgets binary data blob format is
///    similar to JSON. This form is typically not used in applications; it is
///    more common for this format to be used on the server side, parsed and
///    then encoded in binary form for transmission to the client.
///
/// 4. Data in JSON form can be decoded using [JsonCodec.decode] (typically
///    using the [json] object); the JSON decoder creates the same types of data
///    structures as expected by [update]. This is not generally recommended but
///    may be appropriate if the data was obtained from a third-party source in
///    JSON form and could not be preprocessed by a server to convert the data
///    to the binary form described above. Numbers in JSON are interpreted as
///    doubles if they contain a decimal point or an `e` in their source
///    representation, and as integers otherwise. This can cause issues as the
///    [DynamicContent] and [DataSource] are strongly typed and distinguish
///    [int] and [double]. Explicit nulls in the JSON are an error (the data
///    format supported by [DynamicContent] does not support nulls). Decoding
///    JSON is about 1.5x slower than the binary format.
///
/// Subscribers are notified immediately after an update if their data changed.
///
/// ## References
///
/// To subscribe to a node, the [subscribe] method is used. The method returns
/// the current value. When the value later changes, the provided callback is
/// invoked with the new value.
///
/// The [unsubscribe] method must be called when the client no longer needs
/// updates (e.g. when the widget goes away).
///
/// To identify a node, a list of keys is used, giving the path from the root to
/// the node. Each key is either a string (to index into maps) or an integer (to
/// index into lists). If no node is identified, the [missing] value is
/// returned. Similarly, if a node goes away, subscribers are given the value
/// [missing] as the new value. It is not an error to subscribe to missing data.
/// It _is_ an error to add [missing] values to the data model, however.
///
/// The [LocalWidgetBuilder]s passed to a [LocalWidgetLibrary] use a
/// [DataSource] as their interface into the [DynamicContent]. To ensure the
/// integrity of the update mechanism, that interface only allows access to
/// leaves, not intermediate nodes (maps and lists).
///
/// It is an error to subscribe to the same key multiple times with the same
/// callback.
class DynamicContent {
  /// Create a fresh [DynamicContent] object.
  ///
  /// The `initialData` argument, if provided, is used to update all the keys
  /// in the [DynamicContent], as if [updateAll] had been called.
  DynamicContent([ DynamicMap? initialData ]) {
    if (initialData != null) {
      updateAll(initialData);
    }
  }

  final _DynamicNode _root = _DynamicNode.root();

  /// Update all the keys in the [DynamicContent].
  ///
  /// Each key in the provided map is added to [DynamicContent], replacing any
  /// data that was there previously, as if [update] had been called for each
  /// key.
  ///
  /// Existing keys that are not present in the given map are left unmodified.
  void updateAll(DynamicMap initialData) {
    for (final String key in initialData.keys) {
      final Object value = initialData[key] ?? missing;
      update(key, value);
    }
  }

  /// Updates the content with the specified data.
  ///
  /// The given `rootKey` is updated with the data `value`.
  ///
  /// The `value` must consist exclusively of [DynamicMap], [DynamicList], [int],
  /// [double], [bool], and [String] objects.
  void update(String rootKey, Object value) {
    _root.updateKey(rootKey, deepClone(value)!);
    _scheduleCleanup();
  }

  /// Obtain the value at location `key`, and subscribe `callback` to that key
  /// so that future [update]s will invoke the callback with the new value.
  ///
  /// The value is always non-null; if the value is missing, the [missing]
  /// object is used instead.
  ///
  /// Use [unsubscribe] when the subscription is no longer needed.
  Object subscribe(List<Object> key, SubscriptionCallback callback) {
    return _root.subscribe(key, 0, callback);
  }

  /// Removes a subscription created by [subscribe].
  void unsubscribe(List<Object> key, SubscriptionCallback callback) {
    _root.unsubscribe(key, 0, callback);
  }

  bool _cleanupPending = false;

  void _scheduleCleanup() {
    if (!_cleanupPending) {
      _cleanupPending = true;
      scheduleMicrotask(() {
        _cleanupPending = false;
        _DynamicNode.cleanup();
      });
    }
  }

  @override
  String toString() => '$runtimeType($_root)';
}

// Node in the [DynamicContent] tree. This should contain no [BlobNode]s.
class _DynamicNode {
  _DynamicNode(this._key, this._parent, this._value) : assert(_value == missing || _hasValidType(_value));

  _DynamicNode.root() : _key = missing, _parent = null, _value = DynamicMap(); // ignore: prefer_collection_literals

  final Object _key;
  final _DynamicNode? _parent;
  Object _value;

  final Set<SubscriptionCallback> _callbacks = <SubscriptionCallback>{};
  final Map<Object, _DynamicNode> _children = <Object, _DynamicNode>{};

  bool get isObsolete => _callbacks.isEmpty && _children.isEmpty;

  static final Set<_DynamicNode> _obsoleteNodes = <_DynamicNode>{};

  /// Allow garbage collection to collect unused nodes.
  ///
  /// When a node has no subscribers, it is no longer needed (it can be
  /// recreated if necessary from the raw data). In that situation, the node
  /// adds itself to a list of "obsolete nodes", but the parent still references
  /// it and therefore garbage collection would not notice that it is no longer
  /// used.
  ///
  /// This method solves this problem by disconnecting obsolete nodes from the
  /// tree.
  static void cleanup() {
    while (_obsoleteNodes.isNotEmpty) {
      final _DynamicNode node = _obsoleteNodes.first;
      _obsoleteNodes.remove(node);
      if (node.isObsolete) {
        node._parent?._forget(node._key, node);
      }
    }
  }

  void _forget(Object childKey, _DynamicNode child) {
    assert(_children[childKey] == child);
    _children.remove(childKey);
    if (isObsolete) {
      _obsoleteNodes.add(this);
    }
  }

  static bool _hasValidType(Object? value) {
    if (value is DynamicMap) {
      return value.values.every(_hasValidType);
    }
    if (value is DynamicList) {
      return value.every(_hasValidType);
    }
    return value is int
        || value is double
        || value is bool
        || value is String;
  }

  _DynamicNode _prepare(Object childKey) {
    assert(childKey is String || childKey is int);
    if (!_children.containsKey(childKey)) {
      Object value;
      if (_value is DynamicMap) {
        if (childKey is String && (_value as DynamicMap).containsKey(childKey)) {
          value = (_value as DynamicMap)[childKey]!;
        } else {
          value = missing;
        }
      } else if (_value is DynamicList) {
        if (childKey is int && childKey >= 0 && childKey < (_value as DynamicList).length) {
          value = (_value as DynamicList)[childKey]!;
        } else {
          value = missing;
        }
      } else {
        value = _value;
      }
      _children[childKey] = _DynamicNode(childKey, this, value);
    }
    return _children[childKey]!;
  }

  Object subscribe(List<Object> key, int index, SubscriptionCallback callback) {
    _obsoleteNodes.remove(this);
    if (index == key.length) {
      assert(!_callbacks.contains(callback));
      _callbacks.add(callback);
      return _value;
    }
    final _DynamicNode child = _prepare(key[index]);
    return child.subscribe(key, index + 1, callback);
  }

  void unsubscribe(List<Object> key, int index, SubscriptionCallback callback) {
    if (index == key.length) {
      assert(_callbacks.contains(callback));
      _callbacks.remove(callback);
      if (_callbacks.isEmpty) {
        _obsoleteNodes.add(this);
      }
    } else {
      assert(_children.containsKey(key[index]));
      _children[key[index]]!.unsubscribe(key, index + 1, callback);
    }
  }

  void update(Object value) {
    assert(value == missing || _hasValidType(value), 'cannot update $this using $value');
    if (value == _value) {
      return;
    }
    _value = value;
    if (value is DynamicMap) {
      for (final Object childKey in _children.keys) {
        if (childKey is String && value.containsKey(childKey)) {
          _children[childKey]!.update(value[childKey]!);
        } else {
          _children[childKey]!.update(missing);
        }
      }
    } else if (value is DynamicList) {
      for (final Object childKey in _children.keys) {
        if (childKey is int && childKey >= 0 && childKey < value.length) {
          _children[childKey]!.update(value[childKey]!);
        } else {
          _children[childKey]!.update(missing);
        }
      }
    } else {
      for (final _DynamicNode child in _children.values) {
        child.update(missing);
      }
    }
    _sendUpdates(value);
  }

  void _sendUpdates(Object value) {
    for (final SubscriptionCallback callback in _callbacks) {
      callback(value);
    }
  }

  void updateKey(String rootKey, Object value) {
    assert(_value is DynamicMap);
    assert(_hasValidType(value));
    if ((_value as DynamicMap)[rootKey] == value) {
      return;
    }
    (_value as DynamicMap)[rootKey] = value;
    if (_children.containsKey(rootKey)) {
      _children[rootKey]!.update(value);
    }
  }

  @override
  String toString() => '$_value';
}
