// 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/widgets.dart';

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

export '../dart/model.dart' show DynamicMap, LibraryName;

/// Injection point for a remote widget.
///
/// This widget combines an RFW [Runtime] and [DynamicData], inserting a
/// specified [widget] into the tree.
class RemoteWidget extends StatefulWidget {
  /// Inserts the specified [widget] into the tree.
  ///
  /// The [onEvent] argument is optional. When omitted, events are discarded.
  const RemoteWidget({ Key? key, required this.runtime, required this.widget, required this.data, this.onEvent }) : super(key: key);

  /// The [Runtime] to use to render the widget specified by [library] and [name].
  ///
  /// This should update rarely (doing so is relatively expensive), but it is
  /// fine to update it. For example, a client could update this on the fly when
  /// the server deploys a new version of the widget library.
  ///
  /// Frequent updates (e.g. animations) should be done by updating [data] instead.
  final Runtime runtime;

  /// The name of the widget to display, and the library from which to obtain
  /// in.
  ///
  /// The widget must be either declared in the specified library or one of its
  /// dependencies.
  ///
  /// The data to show in the widget is specified using [data].
  final FullyQualifiedWidgetName widget;

  /// The data to which the widget specified by [name] will be bound.
  ///
  /// This includes data that comes from the application, e.g. a description of
  /// the user's device, the current time, or an animation controller's value,
  /// and data that comes from the server, e.g. the contents of the user's
  /// shopping cart.
  ///
  /// This can be updated frequently (once per frame) using
  /// [DynamicContent.update].
  final DynamicContent data;

  /// Called when there's an event triggered by a remote widget.
  ///
  /// If this is null, events are discarded.
  final RemoteEventHandler? onEvent;

  @override
  _RemoteWidgetState createState() => _RemoteWidgetState();
}

class _RemoteWidgetState extends State<RemoteWidget> {
  @override
  void initState() {
    super.initState();
    widget.runtime.addListener(_runtimeChanged);
  }

  @override
  void didUpdateWidget(RemoteWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.runtime != widget.runtime) {
      oldWidget.runtime.removeListener(_runtimeChanged);
      widget.runtime.addListener(_runtimeChanged);
    }
  }

  @override
  void dispose() {
    widget.runtime.removeListener(_runtimeChanged);
    super.dispose();
  }

  void _runtimeChanged() {
    setState(() { /* widget probably changed */ });
  }

  void _eventHandler(String eventName, DynamicMap eventArguments) {
    if (widget.onEvent != null) {
      widget.onEvent!(eventName, eventArguments);
    }
  }

  @override
  Widget build(BuildContext context) {
    return widget.runtime.build(context, widget.widget, widget.data, _eventHandler);
  }
}
