// 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.
  ///
  /// `T` must be one of [int], [double], [bool], or [String].
  ///
  /// If `T` does not match the type of the value obtained, then the method
  /// returns null.
  T? v<T extends Object>(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 the libraries being retained 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 that the RFW runtime will
  /// invoke whenever a remote widget event handler is triggered.
  Widget build(BuildContext context, FullyQualifiedWidgetName widget, DynamicContent data, RemoteEventHandler remoteEventTarget) {
    _CurriedWidget? boundWidget = _widgets[widget];
    if (boundWidget == null) {
      _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) {
    final _ResolvedConstructor? result = _cachedConstructors[fullName];
    if (result != null) {
      return result;
    }
    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) {
          // We cache the constructor under each name that we tried to look it up with, so
          // that next time it takes less time to find it.
          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 `fullName` to a [_ResolvedConstructor], then binds its arguments
  /// to `arguments` (binding any [ArgsReference]s to [BoundArgsReference]s) and
  /// expands any references to [ConstructorCall]s so that all remaining widgets
  /// are [_CurriedWidget]s.
  ///
  /// Widgets can't reference each other recursively; this is enforced using the
  /// `usedWidgets` argument.
  _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;
        final 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 List<Object>.generate(
        node.length,
        (int index) => _bindArguments(context, node[index]!, arguments, stateDepth, usedWidgets),
        growable: false,
      );
    }
    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 List<Object>.generate(
        node.length,
        (int index) => _bindLoopVariable(node[index]!, argument, depth),
        growable: false,
      );
    }
    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 `targetEffectiveIndex` 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) {
    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);
  }

  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) {
        // We've reached the end of the line.
        // We handle some special leaf cases that still need processing before we return.
        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));
        }
        // else `current` is nothing special, and we'll just return it below.
        break; // This is where the loop ends.
      } 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) {
    final Object resolvedWidget = _CurriedWidget._resolveFrom(root, const <Object>[], stateResolver, dataResolver);
    if (resolvedWidget is _CurriedWidget) {
      return resolvedWidget.build(context, data, remoteEventTarget, states);
    }
    return _buildErrorWidget('Switch in $fullName did not resolve to a widget (got $resolvedWidget).');
  }

  @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 extends Object>(List<Object> argsKey) {
    assert(T == int || T == double || T == bool || T == String);
    final Object value = _fetch(argsKey, expandLists: false);
    return value is T ? value : 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 List<Widget>.generate(
        fullList.length,
        (int index) {
          final Object? node = fullList[index];
          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}.');
        },
      );
    }
    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 => Object.hash(section, Object.hashAll(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);
}
