// 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 [widget].
  ///
  /// 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
  /// it.
  ///
  /// The widget must be declared either 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);
  }
}
