// 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 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

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

/// Signature of builders for local widgets.
///
/// The [LocalWidgetLibrary] class wraps a map of widget names to
/// [LocalWidgetBuilder] callbacks.
typedef LocalWidgetBuilder = Widget Function(BuildContext context, DataSource source);

/// Signature of the callback passed to a [RemoteWidget].
///
/// This is used by [RemoteWidget] and [Runtime.build] as the callback for
/// events triggered by remote widgets.
typedef RemoteEventHandler = void Function(String eventName, DynamicMap eventArguments);

/// Signature of the callback passed to [DataSource.handler].
///
/// The callback should return a function of type `T`. That function should call
/// `trigger`.
///
/// See [DataSource.handler] for details.
typedef HandlerGenerator<T extends Function> = T Function(HandlerTrigger trigger);

/// Signature of the callback passed to a [HandlerGenerator].
///
/// See [DataSource.handler] for details.
typedef HandlerTrigger = void Function([DynamicMap? extraArguments]);

/// Used to indicate that there is an error with one of the libraries loaded
/// into the Remote Flutter Widgets [Runtime].
///
/// For example, a reference to a state variable did not match any actual state
/// values, or a library import loop.
class RemoteFlutterWidgetsException implements Exception {
  /// Creates a [RemoteFlutterWidgetsException].
  ///
  /// The message should be a complete sentence, starting with a capital letter
  /// and ending with a period.
  const RemoteFlutterWidgetsException(this.message);

  /// A description of the problem that was detected.
  ///
  /// This will end with a period.
  final String message;

  @override
  String toString() => message;
}

/// Interface for [LocalWidgetBuilder] to obtain data from arguments.
///
/// The interface exposes the [v] method, the argument to which is a list of
/// keys forming a path to a node in the arguments expected by the widget. If
/// the method's type argument does not match the value obtained, null is
/// returned instead.
///
/// In addition, to fetch widgets specifically, the [child] and [childList]
/// methods must be used, and to fetch event handlers, the [handler] method must
/// be used.
///
/// The [isList] and [isMap] methods can be used to avoid inspecting keys that
/// may not be present (e.g. before reading 15 keys in a map that isn't even
/// present, consider checking if the map is present using [isMap] and
/// short-circuiting the key lookups if it is not).
///
/// To iterate over a list, the [length] method can be used to find the number
/// of items in the list.
abstract class DataSource {
  /// Return the int, double, bool, or String value at the given path of the
  /// arguments to the widget.
  ///
  /// If `T` is not [Object] and `T` does not match the type of the value
  /// obtained, then the method returns null.
  T? v<T>(List<Object> argsKey);

  /// Return true if the given key identifies a list, otherwise false.
  bool isList(List<Object> argsKey);

  /// Return the length of the list at the given path of the arguments to the
  /// widget.
  ///
  /// If the given path does not identify a list, returns zero.
  int length(List<Object> argsKey);

  /// Return true if the given key identifies a map, otherwise false.
  bool isMap(List<Object> argsKey);

  /// Build the child at the given key.
  ///
  /// If the node specified is not a widget, returns an [ErrorWidget].
  ///
  /// See also:
  ///
  ///  * [optionalChild], which returns null if the widget is missing.
  Widget child(List<Object> argsKey);

  /// Build the child at the given key.
  ///
  /// If the node specified is not a widget, returns null.
  ///
  /// See also:
  ///
  ///  * [child], which returns an [ErrorWidget] instead of null if the widget
  ///    is missing.
  Widget? optionalChild(List<Object> argsKey);

  /// Builds the children at the given key.
  ///
  /// If the node is missing, returns an empty list.
  ///
  /// If the node specified is not a list of widgets, returns a list with the
  /// non-widget nodes replaced by [ErrorWidget].
  List<Widget> childList(List<Object> argsKey);

  /// Gets a [VoidCallback] event handler at the given key.
  ///
  /// If the node specified is an [AnyEventHandler] or a [DynamicList] of
  /// [AnyEventHandler]s, returns a callback that invokes the specified event
  /// handler(s), merging the given `extraArguments` into the arguments
  /// specified in each event handler. In the event of a key conflict (where
  /// both the arguments specified in the remote widget declaration and the
  /// argument provided to this method have the same name), the arguments
  /// specified here take precedence.
  VoidCallback? voidHandler(List<Object> argsKey, [ DynamicMap? extraArguments ]);

  /// Gets an event handler at the given key.
  ///
  /// The event handler can be of any Function type, as specified by the type
  /// argument `T`.
  ///
  /// When this method is called, the second argument, `generator`, is invoked.
  /// The `generator` callback must return a function, which we will call
  /// _entrypoint_, that matches the signature of `T`. The `generator` callback
  /// receives an argument, which we will call `trigger`. The _entrypoint_
  /// function must call `trigger`, optionally passing it any extra arguments
  /// that should be merged into the arguments specified in each event handler.
  ///
  /// This is admittedly a little confusing. At its core, the problem is that
  /// this method cannot itself automatically create a function (_entrypoint_)
  /// of the right type (`T`), and therefore a callback (`generator`) that knows
  /// how to wrap a function body (`trigger`) in the right signature (`T`) is
  /// needed to actually build that function (_entrypoint_).
  T? handler<T extends Function>(List<Object> argsKey, HandlerGenerator<T> generator);
}

/// Widgets defined by the client application. All remote widgets eventually
/// bottom out in these widgets.
class LocalWidgetLibrary extends WidgetLibrary {
  /// Create a [LocalWidgetLibrary].
  ///
  /// The given map must not change once the object is created.
  LocalWidgetLibrary(this._widgets);

  final Map<String, LocalWidgetBuilder> _widgets;

  /// Returns the builder for the widget of the given name, if any.
  @protected
  LocalWidgetBuilder? findConstructor(String name) {
    return _widgets[name];
  }
}

class _ResolvedConstructor {
  const _ResolvedConstructor(this.fullName, this.constructor);
  final FullyQualifiedWidgetName fullName;
  final Object constructor;
}

/// The logic that builds and maintains Remote Flutter Widgets.
///
/// To declare the libraries of widgets, the [update] method is used.
///
/// At least one [LocalWidgetLibrary] instance must be declared
/// so that [RemoteWidgetLibrary] instances can resolve to real widgets.
///
/// The [build] method returns a [Widget] generated from one of the libraries of
/// widgets added in this manner. Generally, it is simpler to use the
/// [RemoteWidget] widget (which calls [build]).
class Runtime extends ChangeNotifier {
  /// Create a [Runtime] object.
  ///
  /// This object should be [dispose]d when it is no longer needed.
  Runtime();

  final Map<LibraryName, WidgetLibrary> _libraries = <LibraryName, WidgetLibrary>{};

  /// Replace the definitions of the specified library (`name`).
  ///
  /// References to widgets that are not defined in the available libraries will
  /// default to using the [ErrorWidget] widget.
  ///
  /// [LocalWidgetLibrary] and [RemoteWidgetLibrary] instances are added using
  /// this method.
  ///
  /// [RemoteWidgetLibrary] instances are typically first obtained using
  /// [decodeLibraryBlob].
  ///
  /// To remove a library, the libraries must be cleared using [clearLibraries]
  /// and then all the libraries must be readded.
  void update(LibraryName name, WidgetLibrary library) {
    _libraries[name] = library;
    _clearCache();
  }

  /// Remove all the libraries and start afresh.
  ///
  /// Calling this notifies the listeners, which typically causes them to
  /// rebuild their widgets in the next frame (for example, that is how
  /// [RemoteWidget] is implemented). If no libraries are readded after calling
  /// [clearLibraries], and there are any listeners, they will fail to rebuild
  /// any widgets that they were configured to create. For this reason, this
  /// call should usually be immediately followed by calls to [update].
  void clearLibraries() {
    _libraries.clear();
    _clearCache();
  }

  final Map<FullyQualifiedWidgetName, _ResolvedConstructor?> _cachedConstructors = <FullyQualifiedWidgetName, _ResolvedConstructor?>{};
  final Map<FullyQualifiedWidgetName, _CurriedWidget> _widgets = <FullyQualifiedWidgetName, _CurriedWidget>{};

  void _clearCache() {
    _cachedConstructors.clear();
    _widgets.clear();
    notifyListeners();
  }

  /// Build the root widget of a Remote Widget subtree.
  ///
  /// The widget is identified by a [FullyQualifiedWidgetName], which identifies
  /// a library and a widget name. The widget does not strictly have to be in
  /// that library, so long as it is in that library's dependencies.
  ///
  /// The data for the widget is given by the `data` argument. That object can
  /// be updated independently, the widget will rebuild appropriately as it
  /// changes.
  ///
  /// The `remoteEventTarget` argument is the callback to invoke whenever a
  /// remote widget event handler is triggered.
  Widget build(BuildContext context, FullyQualifiedWidgetName widget, DynamicContent data, RemoteEventHandler remoteEventTarget) {
    final _CurriedWidget boundWidget;
    if (_widgets.containsKey(widget)) {
      boundWidget = _widgets[widget]!;
    } else {
      _checkForImportLoops(widget.library);
      boundWidget = _applyConstructorAndBindArguments(widget, const <String, Object?>{}, -1, <FullyQualifiedWidgetName>{});
      _widgets[widget] = boundWidget;
    }
    return boundWidget.build(context, data, remoteEventTarget, const <_WidgetState>[]);
  }

  void _checkForImportLoops(LibraryName name, [ Set<LibraryName>? visited ]) {
    final WidgetLibrary? library = _libraries[name];
    if (library is RemoteWidgetLibrary) {
      visited ??= <LibraryName>{};
      visited.add(name);
      for (final Import import in library.imports) {
        final LibraryName dependency = import.name;
        if (visited.contains(dependency)) {
          final List<LibraryName> path = <LibraryName>[dependency];
          for (final LibraryName name in visited.toList().reversed) {
            if (name == dependency) {
              break;
            }
            path.add(name);
          }
          if (path.length == 1) {
            assert(path.single == dependency);
            throw RemoteFlutterWidgetsException('Library $dependency depends on itself.');
          } else {
            throw RemoteFlutterWidgetsException('Library $dependency indirectly depends on itself via ${path.reversed.join(" which depends on ")}.');
          }
        }
        _checkForImportLoops(dependency, visited.toSet());
      }
    }
  }

  _ResolvedConstructor? _findConstructor(FullyQualifiedWidgetName fullName) {
    if (_cachedConstructors.containsKey(fullName)) {
      return _cachedConstructors[fullName];
    }
    final WidgetLibrary? library = _libraries[fullName.library];
    if (library is RemoteWidgetLibrary) {
      for (final WidgetDeclaration constructor in library.widgets) {
        if (constructor.name == fullName.widget) {
          return _cachedConstructors[fullName] = _ResolvedConstructor(fullName, constructor);
        }
      }
      for (final Import import in library.imports) {
        final LibraryName dependency = import.name;
        final _ResolvedConstructor? result = _findConstructor(FullyQualifiedWidgetName(dependency, fullName.widget));
        if (result != null) {
          return _cachedConstructors[fullName] = result;
        }
      }
    } else if (library is LocalWidgetLibrary) {
      final LocalWidgetBuilder? constructor = library.findConstructor(fullName.widget);
      if (constructor != null) {
        return _cachedConstructors[fullName] = _ResolvedConstructor(fullName, constructor);
      }
    } else {
      assert(library is Null); // ignore: prefer_void_to_null, type_check_with_null, https://github.com/dart-lang/sdk/issues/47017#issuecomment-907562014
    }
    _cachedConstructors[fullName] = null;
    return null;
  }

  Iterable<LibraryName> _findMissingLibraries(LibraryName library) sync* {
    final WidgetLibrary? root = _libraries[library];
    if (root == null) {
      yield library;
      return;
    }
    if (root is LocalWidgetLibrary) {
      return;
    }
    root as RemoteWidgetLibrary;
    for (final Import import in root.imports) {
      yield* _findMissingLibraries(import.name);
    }
  }

  /// Resolves argument references ([ArgsReference] objects) in the given
  /// `node`, and applies [ConstructorCall]s so that all remaining widgets are
  /// local widgets.
  _CurriedWidget _applyConstructorAndBindArguments(FullyQualifiedWidgetName fullName, DynamicMap arguments, int stateDepth, Set<FullyQualifiedWidgetName> usedWidgets) {
    final _ResolvedConstructor? widget = _findConstructor(fullName);
    if (widget != null) {
      if (widget.constructor is WidgetDeclaration) {
        if (usedWidgets.contains(widget.fullName)) {
          return _CurriedLocalWidget.error(fullName, 'Widget loop: Tried to call ${widget.fullName} constructor reentrantly.');
        }
        usedWidgets = usedWidgets.toSet()..add(widget.fullName);
        final WidgetDeclaration constructor = widget.constructor as WidgetDeclaration;
        int newDepth;
        if (constructor.initialState != null) {
          newDepth = stateDepth + 1;
        } else {
          newDepth = stateDepth;
        }
        Object result = _bindArguments(widget.fullName, constructor.root, arguments, newDepth, usedWidgets);
        if (result is Switch) {
          result = _CurriedSwitch(widget.fullName, result, arguments, constructor.initialState);
        } else {
          result as _CurriedWidget;
          if (constructor.initialState != null) {
            result = _CurriedRemoteWidget(widget.fullName, result, arguments, constructor.initialState);
          }
        }
        return result as _CurriedWidget;
      }
      assert(widget.constructor is LocalWidgetBuilder);
      return _CurriedLocalWidget(widget.fullName, widget.constructor as LocalWidgetBuilder, arguments);
    }
    final Set<LibraryName> missingLibraries = _findMissingLibraries(fullName.library).toSet();
    if (missingLibraries.isNotEmpty) {
      return _CurriedLocalWidget.error(
        fullName,
        'Could not find remote widget named ${fullName.widget} in ${fullName.library}, '
        'possibly because some dependencies were missing: ${missingLibraries.join(", ")}',
      );
    }
    return _CurriedLocalWidget.error(fullName, 'Could not find remote widget named ${fullName.widget} in ${fullName.library}.');
  }

  Object _bindArguments(FullyQualifiedWidgetName context, Object node, Object arguments, int stateDepth, Set<FullyQualifiedWidgetName> usedWidgets) {
    if (node is ConstructorCall) {
      final DynamicMap subArguments = _bindArguments(context, node.arguments, arguments, stateDepth, usedWidgets) as DynamicMap;
      return _applyConstructorAndBindArguments(FullyQualifiedWidgetName(context.library, node.name), subArguments, stateDepth, usedWidgets);
    }
    if (node is DynamicMap) {
      return node.map<String, Object?>(
        (String name, Object? value) => MapEntry<String, Object?>(name, _bindArguments(context, value!, arguments, stateDepth, usedWidgets)),
      );
    }
    if (node is DynamicList) {
      return node.map<Object>(
        (Object? value) => _bindArguments(context, value!, arguments, stateDepth, usedWidgets),
      ).toList();
    }
    if (node is Loop) {
      final Object input = _bindArguments(context, node.input, arguments, stateDepth, usedWidgets);
      final Object output = _bindArguments(context, node.output, arguments, stateDepth, usedWidgets);
      return Loop(input, output);
    }
    if (node is Switch) {
      return Switch(
        _bindArguments(context, node.input, arguments, stateDepth, usedWidgets),
        node.outputs.map<Object?, Object>(
          (Object? key, Object value) {
            return MapEntry<Object?, Object>(
              key == null ? key : _bindArguments(context, key, arguments, stateDepth, usedWidgets),
              _bindArguments(context, value, arguments, stateDepth, usedWidgets),
            );
          },
        ),
      );
    }
    if (node is ArgsReference) {
      return node.bind(arguments);
    }
    if (node is StateReference) {
      return node.bind(stateDepth);
    }
    if (node is EventHandler) {
      return EventHandler(node.eventName, _bindArguments(context, node.eventArguments, arguments, stateDepth, usedWidgets) as DynamicMap);
    }
    if (node is SetStateHandler) {
      assert(node.stateReference is StateReference);
      final BoundStateReference stateReference = (node.stateReference as StateReference).bind(stateDepth);
      return SetStateHandler(stateReference, _bindArguments(context, node.value, arguments, stateDepth, usedWidgets));
    }
    assert(node is! WidgetDeclaration);
    return node;
  }
}

// Internal structure to represent the result of indexing into a list.
//
// There are two ways this can go: either we index in and find a result, in
// which case [result] is that value and the other fields are null, or we fail
// to index into the list and we obtain the length as a side-effect, in which
// case [result] is null, [rawList] is the raw list (might contain [Loop] objects),
// and [length] is the effective length after expanding all the internal loops.
class _ResolvedDynamicList {
  const _ResolvedDynamicList(this.rawList, this.result, this.length);
  final DynamicList? rawList;
  final Object? result; // null means out of range
  final int? length; // might be null if result is not null
}

typedef _DataResolverCallback = Object Function(List<Object> dataKey);
typedef _StateResolverCallback = Object Function(List<Object> stateKey, int depth);

abstract class _CurriedWidget extends BlobNode {
  const _CurriedWidget(this.fullName, this.arguments, this.initialState);

  final FullyQualifiedWidgetName fullName;
  final DynamicMap arguments;
  final DynamicMap? initialState;

  static Object _bindLoopVariable(Object node, Object argument, int depth) {
    if (node is DynamicMap) {
      return node.map<String, Object?>(
        (String name, Object? value) => MapEntry<String, Object?>(name, _bindLoopVariable(value!, argument, depth)),
      );
    }
    if (node is DynamicList) {
      return node.map<Object>(
        (Object? value) => _bindLoopVariable(value!, argument, depth),
      ).toList();
    }
    if (node is Loop) {
      return Loop(_bindLoopVariable(node.input, argument, depth), _bindLoopVariable(node.output, argument, depth + 1));
    }
    if (node is Switch) {
      return Switch(
        _bindLoopVariable(node.input, argument, depth),
        node.outputs.map<Object?, Object>(
          (Object? key, Object value) => MapEntry<Object?, Object>(
            key == null ? null : _bindLoopVariable(key, argument, depth),
            _bindLoopVariable(value, argument, depth),
          ),
        )
      );
    }
    if (node is _CurriedLocalWidget) {
      return _CurriedLocalWidget(
        node.fullName,
        node.child,
        _bindLoopVariable(node.arguments, argument, depth) as DynamicMap,
      );
    }
    if (node is _CurriedRemoteWidget) {
      return _CurriedRemoteWidget(
        node.fullName,
        _bindLoopVariable(node.child, argument, depth) as _CurriedWidget,
        _bindLoopVariable(node.arguments, argument, depth) as DynamicMap,
        node.initialState,
      );
    }
    if (node is _CurriedSwitch) {
      return _CurriedSwitch(
        node.fullName,
        _bindLoopVariable(node.root, argument, depth) as Switch,
        _bindLoopVariable(node.arguments, argument, depth) as DynamicMap,
        node.initialState,
      );
    }
    if (node is LoopReference) {
      if (node.loop == depth) {
        return node.bind(argument);
      }
      return node;
    }
    if (node is BoundArgsReference) {
      return BoundArgsReference(_bindLoopVariable(node.arguments, argument, depth), node.parts);
    }
    if (node is EventHandler) {
      return EventHandler(node.eventName, _bindLoopVariable(node.eventArguments, argument, depth) as DynamicMap);
    }
    if (node is SetStateHandler) {
      return SetStateHandler(node.stateReference, _bindLoopVariable(node.value, argument, depth));
    }
    return node;
  }

  /// Look up the _index_th entry in `list`, expanding any loops in `list`.
  ///
  /// If `index` is -1, this evaluates the entire list to ensure the length is available.
  //
  // TODO(ianh): This really should have some sort of caching. Right now, evaluating a whole list
  // ends up being around O(N^2) since we have to walk the list from the start for every entry.
  static _ResolvedDynamicList _listLookup(DynamicList list, int targetEffectiveIndex, _StateResolverCallback stateResolver, _DataResolverCallback dataResolver) {
    if (list.any((Object? entry) => entry is Loop)) {
      int currentIndex = 0; // where we are in `list` (some entries of which might represent multiple values, because they are themselves loops)
      int effectiveIndex = 0; // where we are in the fully expanded list (the coordinate space in which we're aiming for `targetEffectiveIndex`)
      while ((effectiveIndex <= targetEffectiveIndex || targetEffectiveIndex < 0) && currentIndex < list.length) {
        final Object node = list[currentIndex]!;
        if (node is Loop) {
          Object inputList = node.input;
          while (inputList is! DynamicList) {
            if (inputList is BoundArgsReference) {
              inputList = _resolveFrom(inputList.arguments, inputList.parts, stateResolver, dataResolver);
            } else if (inputList is DataReference) {
              inputList = dataResolver(inputList.parts);
            } else if (inputList is BoundStateReference) {
              inputList = stateResolver(inputList.parts, inputList.depth);
            } else if (inputList is BoundLoopReference) {
              inputList = _resolveFrom(inputList.value, inputList.parts, stateResolver, dataResolver);
            } else if (inputList is Switch) {
              inputList = _resolveFrom(inputList, const <Object>[], stateResolver, dataResolver);
            } else {
              // e.g. it's a map or something else that isn't indexable
              inputList = DynamicList.empty();
            }
            assert(inputList is! _ResolvedDynamicList);
          }
          final _ResolvedDynamicList entry = _listLookup(inputList, targetEffectiveIndex >= 0 ? targetEffectiveIndex - effectiveIndex : -1, stateResolver, dataResolver);
          if (entry.result != null) {
            final Object boundResult = _bindLoopVariable(node.output, entry.result!, 0);
            return _ResolvedDynamicList(null, boundResult, null);
          }
          effectiveIndex += entry.length!;
        } else { // list[currentIndex] is not a Loop
          if (effectiveIndex == targetEffectiveIndex) {
            return _ResolvedDynamicList(null, list[currentIndex], null);
          }
          effectiveIndex += 1;
        }
        currentIndex += 1;
      }
      return _ResolvedDynamicList(list, null, effectiveIndex);
    } else {
      if (targetEffectiveIndex < 0 || targetEffectiveIndex >= list.length) {
        return _ResolvedDynamicList(list, null, list.length);
      }
      return _ResolvedDynamicList(list, list[targetEffectiveIndex]!, list.length);
    }
  }

  static Object _resolveFrom(Object root, List<Object> parts, _StateResolverCallback stateResolver, _DataResolverCallback dataResolver) {
    int index = 0;
    Object current = root;
    while (true) {
      if (current is DataReference) {
        if (index < parts.length) {
          current = current.constructReference(parts.sublist(index));
          index = parts.length;
        }
        current = dataResolver(current.parts);
        continue;
      } else if (current is BoundArgsReference) {
        List<Object> nextParts = current.parts;
        if (index < parts.length) {
          nextParts += parts.sublist(index);
        }
        parts = nextParts;
        current = current.arguments;
        index = 0;
        continue;
      } else if (current is BoundStateReference) {
        if (index < parts.length) {
          current = current.constructReference(parts.sublist(index));
          index = parts.length;
        }
        current = stateResolver(current.parts, current.depth);
        continue;
      } else if (current is BoundLoopReference) {
        List<Object> nextParts = current.parts;
        if (index < parts.length) {
          nextParts += parts.sublist(index);
        }
        parts = nextParts;
        current = current.value;
        index = 0;
        continue;
      } else if (current is Switch) {
        final Object key = _resolveFrom(current.input, const <Object>[], stateResolver, dataResolver);
        Object? value = current.outputs[key];
        if (value == null) {
          value = current.outputs[null];
          if (value == null) {
            return missing;
          }
        }
        current = value;
        continue;
      } else if (index >= parts.length) {
        if (current is EventHandler) {
          current = EventHandler(current.eventName, _fix(current.eventArguments, stateResolver, dataResolver) as DynamicMap);
        } else if (current is SetStateHandler) {
          current = SetStateHandler(current.stateReference, _fix(current.value, stateResolver, dataResolver));
        }
        break;
      } else if (current is DynamicMap) {
        if (parts[index] is! String) {
          return missing;
        }
        if (!current.containsKey(parts[index])) {
          return missing;
        }
        current = current[parts[index]]!;
      } else if (current is DynamicList) {
        if (parts[index] is! int) {
          return missing;
        }
        current = _listLookup(current, parts[index] as int, stateResolver, dataResolver).result ?? missing;
      } else {
        assert(current is! ArgsReference);
        assert(current is! StateReference);
        assert(current is! LoopReference);
        return missing;
      }
      index += 1;
    }
    assert(current is! Reference, 'Unexpected unbound reference (of type ${current.runtimeType}): $current');
    assert(current is! Switch);
    assert(current is! Loop);
    return current;
  }

  static Object _fix(Object root, _StateResolverCallback stateResolver, _DataResolverCallback dataResolver) {
    if (root is DynamicMap) {
      return root.map((String key, Object? value) => MapEntry<String, Object?>(key, _fix(root[key]!, stateResolver, dataResolver)));
    } else if (root is DynamicList) {
      if (root.any((Object? entry) => entry is Loop)) {
        final int length = _listLookup(root, -1, stateResolver, dataResolver).length!;
        return DynamicList.generate(length, (int index) => _fix(_listLookup(root, index, stateResolver, dataResolver).result!, stateResolver, dataResolver));
      } else {
        return DynamicList.generate(root.length, (int index) => _fix(root[index]!, stateResolver, dataResolver));
      }
    } else if (root is BlobNode) {
      return _resolveFrom(root, const <Object>[], stateResolver, dataResolver);
    } else {
      return root;
    }
  }

  Object resolve(List<Object> parts, _StateResolverCallback stateResolver, _DataResolverCallback dataResolver, { required bool expandLists }) {
    Object result = _resolveFrom(arguments, parts, stateResolver, dataResolver);
    if (result is DynamicList && expandLists) {
      result = _listLookup(result, -1, stateResolver, dataResolver);
    }
    assert(result is! Reference);
    assert(result is! Switch);
    assert(result is! Loop);
    return result;
  }

  Widget build(BuildContext context, DynamicContent data, RemoteEventHandler remoteEventTarget, List<_WidgetState> states) {
    return _Widget(curriedWidget: this, data: data, remoteEventTarget: remoteEventTarget, states: states);
  }

  Widget buildChild(BuildContext context, DataSource source, DynamicContent data, RemoteEventHandler remoteEventTarget, List<_WidgetState> states, _StateResolverCallback stateResolver, _DataResolverCallback dataResolver);

  @override
  String toString() => '$fullName ${initialState ?? "{}"} $arguments';
}

class _CurriedLocalWidget extends _CurriedWidget {
  const _CurriedLocalWidget(FullyQualifiedWidgetName fullName, this.child, DynamicMap arguments) : super(fullName, arguments, null);

  factory _CurriedLocalWidget.error(FullyQualifiedWidgetName fullName, String message) {
    return _CurriedLocalWidget(fullName, (BuildContext context, DataSource data) => _buildErrorWidget(message), const <String, Object?>{});
  }

  final LocalWidgetBuilder child;

  @override
  Widget buildChild(BuildContext context, DataSource source, DynamicContent data, RemoteEventHandler remoteEventTarget, List<_WidgetState> states,  _StateResolverCallback stateResolver, _DataResolverCallback dataResolver) {
    return child(context, source);
  }
}

class _CurriedRemoteWidget extends _CurriedWidget {
  const _CurriedRemoteWidget(FullyQualifiedWidgetName fullName, this.child, DynamicMap arguments, DynamicMap? initialState) : super(fullName, arguments, initialState);

  final _CurriedWidget child;

  @override
  Widget buildChild(BuildContext context, DataSource source, DynamicContent data, RemoteEventHandler remoteEventTarget, List<_WidgetState> states,  _StateResolverCallback stateResolver, _DataResolverCallback dataResolver) {
    return child.build(context, data, remoteEventTarget, states);
  }

  @override
  String toString() => '${super.toString()} = $child';
}

class _CurriedSwitch extends _CurriedWidget {
  const _CurriedSwitch(FullyQualifiedWidgetName fullName, this.root, DynamicMap arguments, DynamicMap? initialState) : super(fullName, arguments, initialState);

  final Switch root;

  @override
  Widget buildChild(BuildContext context, DataSource source, DynamicContent data, RemoteEventHandler remoteEventTarget, List<_WidgetState> states,  _StateResolverCallback stateResolver, _DataResolverCallback dataResolver) {
    Object result = _CurriedWidget._resolveFrom(root, const <Object>[], stateResolver, dataResolver);
    if (result is _CurriedWidget) {
      result = result.build(context, data, remoteEventTarget, states);
      return result as Widget;
    }
    return _buildErrorWidget('Switch in $fullName did not resolve to a widget (got $result).');
  }

  @override
  String toString() => '${super.toString()} = $root';
}

class _Widget extends StatefulWidget {
  const _Widget({ Key? key, required this.curriedWidget, required this.data, required this.remoteEventTarget, required this.states }) : super(key: key);

  final _CurriedWidget curriedWidget;

  final DynamicContent data;

  final RemoteEventHandler remoteEventTarget;

  final List<_WidgetState> states;

  @override
  State<_Widget> createState() => _WidgetState();
}

class _WidgetState extends State<_Widget> implements DataSource {
  DynamicContent? _state;
  DynamicMap? _stateStore;
  late List<_WidgetState> _states;

  @override
  void initState() {
    super.initState();
    _updateState();
  }

  @override
  void didUpdateWidget(_Widget oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.curriedWidget != widget.curriedWidget) {
      _updateState();
    }
    if (oldWidget.data != widget.data || oldWidget.curriedWidget != widget.curriedWidget || oldWidget.states != widget.states) {
      _unsubscribe();
    }
  }

  @override
  void dispose() {
    _unsubscribe();
    super.dispose();
  }

  void _updateState() {
    _stateStore = deepClone(widget.curriedWidget.initialState) as DynamicMap?;
    if (_stateStore != null) {
      _state ??= DynamicContent();
      _state!.updateAll(_stateStore!);
    } else {
      _state = null;
    }
    _states = widget.states;
    if (_state != null) {
      _states = _states.toList()..add(this);
    }
  }

  void _handleSetState(int depth, List<Object> parts, Object value) {
    _states[depth].applySetState(parts, value);
  }

  void applySetState(List<Object> parts, Object value) {
    assert(parts.isNotEmpty);
    assert(_stateStore != null);
    int index = 0;
    Object current = _stateStore!;
    while (index < parts.length) {
      final Object subindex = parts[index];
      if (current is DynamicMap) {
        if (subindex is! String) {
          throw RemoteFlutterWidgetsException('${parts.join(".")} does not identify existing state.');
        }
        if (!current.containsKey(subindex)) {
          throw RemoteFlutterWidgetsException('${parts.join(".")} does not identify existing state.');
        }
        if (index == parts.length - 1) {
          current[subindex] = value;
        } else {
          current = current[parts[index]]!;
        }
      } else if (current is DynamicList) {
        if (subindex is! int) {
          throw RemoteFlutterWidgetsException('${parts.join(".")} does not identify existing state.');
        }
        if (subindex < 0 || subindex >= current.length) {
          throw RemoteFlutterWidgetsException('${parts.join(".")} does not identify existing state.');
        }
        if (index == parts.length - 1) {
          current[subindex] = value;
        } else {
          current = current[subindex]!;
        }
      } else {
        throw RemoteFlutterWidgetsException('${parts.join(".")} does not identify existing state.');
      }
      index += 1;
    }
    _state!.updateAll(_stateStore!);
  }

  // List of subscriptions into [widget.data].
  //
  // Keys are into the [DynamicContent] object.
  final Map<_Key, _Subscription> _subscriptions = <_Key, _Subscription>{};

  void _unsubscribe() {
    for (final _Subscription value in _subscriptions.values) {
      value.dispose();
    }
    _subscriptions.clear();
    _argsCache.clear();
  }

  @override
  T? v<T>(List<Object> argsKey) {
    assert(T == Object || T == int || T == double || T == bool || T == String);
    final Object value = _fetch(argsKey, expandLists: false);
    return value is T ? value as T : null;
  }

  @override
  bool isList(List<Object> argsKey) {
    final Object value = _fetch(argsKey, expandLists: false);
    return value is _ResolvedDynamicList
        || value is DynamicList;
  }

  @override
  int length(List<Object> argsKey) {
    final Object value = _fetch(argsKey, expandLists: true);
    if (value is _ResolvedDynamicList) {
      if (value.rawList != null) {
        assert(value.length != null);
        return value.length!;
      }
    }
    assert(value is! DynamicList);
    return 0;
  }

  @override
  bool isMap(List<Object> argsKey) {
    final Object value = _fetch(argsKey, expandLists: false);
    return value is DynamicMap;
  }

  @override
  Widget child(List<Object> argsKey) {
    final Object value = _fetch(argsKey, expandLists: false);
    if (value is _CurriedWidget) {
      return value.build(context, widget.data, widget.remoteEventTarget, widget.states);
    }
    return _buildErrorWidget('Not a widget at $argsKey (got $value) for ${widget.curriedWidget.fullName}.');
  }

  @override
  Widget? optionalChild(List<Object> argsKey) {
    final Object value = _fetch(argsKey, expandLists: false);
    if (value is _CurriedWidget) {
      return value.build(context, widget.data, widget.remoteEventTarget, widget.states);
    }
    return null;
  }

  @override
  List<Widget> childList(List<Object> argsKey) {
    final Object value = _fetch(argsKey, expandLists: true);
    if (value is _ResolvedDynamicList) {
      assert(value.length != null);
      final DynamicList fullList = _fetchList(argsKey, value.length!);
      return fullList.map<Widget>((Object? node) {
        if (node is _CurriedWidget) {
          return node.build(context, widget.data, widget.remoteEventTarget, _states);
        }
        return _buildErrorWidget('Not a widget at $argsKey (got $node) for ${widget.curriedWidget.fullName}.');
      }).toList();
    }
    if (value == missing) {
      return const <Widget>[];
    }
    return <Widget>[
      _buildErrorWidget('Not a widget list at $argsKey (got $value) for ${widget.curriedWidget.fullName}.'),
    ];
  }

  @override
  VoidCallback? voidHandler(List<Object> argsKey, [ DynamicMap? extraArguments ]) {
    return handler<VoidCallback>(argsKey, (HandlerTrigger callback) => () => callback(extraArguments));
  }

  @override
  T? handler<T extends Function>(List<Object> argsKey, HandlerGenerator<T> generator) {
    Object value = _fetch(argsKey, expandLists: true);
    if (value is AnyEventHandler) {
      value = <Object>[ value ];
    } else if (value is _ResolvedDynamicList) {
      value = _fetchList(argsKey, value.length!);
    }
    if (value is DynamicList) {
      final List<AnyEventHandler> handlers = value.whereType<AnyEventHandler>().toList();
      if (handlers.isNotEmpty) {
        return generator(([DynamicMap? extraArguments]) {
          for (final AnyEventHandler entry in handlers) {
            if (entry is EventHandler) {
              DynamicMap arguments = entry.eventArguments;
              if (extraArguments != null) {
                arguments = DynamicMap.fromEntries(arguments.entries.followedBy(extraArguments.entries));
              }
              widget.remoteEventTarget(entry.eventName, arguments);
            } else if (entry is SetStateHandler) {
              assert(entry.stateReference is BoundStateReference);
              _handleSetState((entry.stateReference as BoundStateReference).depth, entry.stateReference.parts, entry.value);
            }
          }
        });
      }
    }
    return null;
  }

  // null values means the data is not in the cache
  final Map<_Key, Object?> _argsCache = <_Key, Object?>{};

  bool _debugFetching = false;
  final List<_Subscription> _dependencies = <_Subscription>[];

  Object _fetch(List<Object> argsKey, { required bool expandLists }) {
    final _Key key = _Key(_kArgsSection, argsKey);
    final Object? value = _argsCache[key];
    if (value != null && (value is! DynamicList || !expandLists)) {
      return value;
    }
    assert(!_debugFetching);
    try {
      _debugFetching = true;
      final Object result = widget.curriedWidget.resolve(argsKey, _stateResolver, _dataResolver, expandLists: expandLists);
      for (final _Subscription subscription in _dependencies) {
        subscription.addClient(key);
      }
      _argsCache[key] = result;
      return result;
    } finally {
      _dependencies.clear();
      _debugFetching = false;
    }
  }

  DynamicList _fetchList(List<Object> argsKey, int length) {
    return DynamicList.generate(length, (int index) {
      return _fetch(<Object>[...argsKey, index], expandLists: false);
    });
  }

  Object _dataResolver(List<Object> rawDataKey) {
    final _Key dataKey = _Key(_kDataSection, rawDataKey);
    final _Subscription subscription;
    if (!_subscriptions.containsKey(dataKey)) {
      subscription = _Subscription(widget.data, this, rawDataKey);
      _subscriptions[dataKey] = subscription;
    } else {
      subscription = _subscriptions[dataKey]!;
    }
    _dependencies.add(subscription);
    return subscription.value;
  }

  Object _stateResolver(List<Object> rawStateKey, int depth) {
    final _Key stateKey = _Key(depth, rawStateKey);
    final _Subscription subscription;
    if (!_subscriptions.containsKey(stateKey)) {
      if (depth >= _states.length) {
        throw const RemoteFlutterWidgetsException('Reference to state value did not correspond to any stateful remote widget.');
      }
      final DynamicContent? state = _states[depth]._state;
      if (state == null) {
        return missing;
      }
      subscription = _Subscription(state, this, rawStateKey);
      _subscriptions[stateKey] = subscription;
    } else {
      subscription = _subscriptions[stateKey]!;
    }
    _dependencies.add(subscription);
    return subscription.value;
  }

  void updateData(Set<_Key> affectedArgs) {
    setState(() {
      for (final _Key key in affectedArgs) {
        _argsCache[key] = null;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    // TODO(ianh): what if this creates some _dependencies?
    return widget.curriedWidget.buildChild(context, this, widget.data, widget.remoteEventTarget, _states, _stateResolver, _dataResolver);
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('name', '${widget.curriedWidget.fullName}'));
  }
}

const int _kDataSection = -1;
const int _kArgsSection = -2;

@immutable
class _Key {
  _Key(this.section, this.parts) : assert(_isValidKey(parts), '$parts is not a valid key');

  static bool _isValidKey(List<Object> parts) {
    return parts.every((Object segment) => segment is int || segment is String);
  }

  final int section;
  final List<Object> parts;

  @override
  bool operator ==(Object other) {
    return other is _Key // _Key has no subclasses, don't need to check runtimeType
        && section == other.section
        && listEquals(parts, other.parts);
  }

  @override
  int get hashCode => hashValues(section, hashList(parts));
}

class _Subscription {
  _Subscription(this._data, this._state, this._dataKey) {
    _update(_data.subscribe(_dataKey, _update));
  }

  final DynamicContent _data;
  final _WidgetState _state;
  final List<Object> _dataKey;
  final Set<_Key> _clients = <_Key>{};

  Object get value => _value;
  late Object _value;

  void _update(Object value) {
    _state.updateData(_clients);
    _value = value;
  }

  void addClient(_Key key) {
    _clients.add(key);
  }

  void dispose() {
    _data.unsubscribe(_dataKey, _update);
  }
}

ErrorWidget _buildErrorWidget(String message) {
  FlutterError.reportError(FlutterErrorDetails(
    exception: message,
    stack: StackTrace.current,
    library: 'Remote Flutter Widgets',
  ));
  return ErrorWidget(message);
}
