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

import 'dart:typed_data';

import 'package:fidl/fidl.dart' show InterfaceHandle;
import 'package:fidl_fuchsia_mem/fidl.dart' show Buffer;
import 'package:fidl_fuchsia_skia_skottie/fidl.dart' as skottie;
import 'package:fidl_fuchsia_sys/fidl.dart';
import 'package:fidl_fuchsia_ui_app/fidl.dart' show ViewProviderProxy;
import 'package:fidl_fuchsia_ui_views/fidl_async.dart'
    show ViewToken, ViewHolderToken;
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:fuchsia_scenic_flutter/child_view.dart' show ChildView;
import 'package:fuchsia_scenic_flutter/child_view_connection.dart'
    show ChildViewConnection;
import 'package:lib.app.dart/app.dart';
import 'package:meta/meta.dart';
import 'package:zircon/zircon.dart';

typedef LoadCallback = void Function(
    skottie.Status status, skottie.Player player);

/// A [Widget] that displays lottie animation in a scenic view.
class LottiePlayer extends StatefulWidget {
  /// The JSON data of the animation as a string.
  final String json;

  /// The background color.
  final Color backgroundColor;

  /// Called after animation is loaded.
  final LoadCallback onLoad;

  /// Loops the animation. Default [true].
  final bool loop;

  /// Starts playing the animation after loading. Default [true].
  final bool autoplay;

  /// Constructor.
  const LottiePlayer({
    @required this.json,
    this.backgroundColor = Colors.black,
    this.loop = true,
    this.autoplay = true,
    Key key,
    this.onLoad,
  }) : super(key: key);

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

class _LottiePlayerState extends State<LottiePlayer> {
  final ComponentControllerProxy _controller = ComponentControllerProxy();
  final skottie.LoaderProxy _loader = skottie.LoaderProxy();
  ChildViewConnection _connection;

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

    _launchViewer();
    _loadViewer();
  }

  @override
  void didUpdateWidget(LottiePlayer old) {
    super.didUpdateWidget(old);
    if (old.json == widget.json &&
        old.backgroundColor == widget.backgroundColor &&
        old.loop == widget.loop &&
        old.autoplay == widget.autoplay) {
      return;
    }

    _loadViewer();
  }

  @override
  void dispose() {
    _loader?.ctrl?.close();
    _controller?.ctrl?.close();
    _connection = null;

    super.dispose();
  }

  @override
  Widget build(BuildContext context) => ChildView(
        connection: _connection,
        hitTestable: false,
        focusable: false,
      );

  void _launchViewer() {
    final startupContext = StartupContext.fromStartupInfo();
    final incomingServices = Services();

    final launcher = LauncherProxy();
    connectToService(startupContext.environmentServices, launcher.ctrl);
    launcher.createComponent(
      LaunchInfo(
        url: 'skottie_viewer',
        directoryRequest: incomingServices.request(),
      ),
      _controller.ctrl.request(),
    );
    launcher.ctrl.close();

    final viewTokens = EventPairPair();
    assert(viewTokens.status == ZX.OK);
    final viewHolderToken = ViewHolderToken(value: viewTokens.first);
    final viewToken = ViewToken(value: viewTokens.second);

    final viewProvider = ViewProviderProxy();
    incomingServices.connectToService(viewProvider.ctrl);
    viewProvider.createView(viewToken.value, null, null);
    viewProvider.ctrl.close();

    incomingServices
      ..connectToService(_loader.ctrl)
      ..close();

    _connection = ChildViewConnection(viewHolderToken);
  }

  void _loadViewer() {
    final SizedVmo vmo =
        SizedVmo.fromUint8List(Uint8List.fromList(widget.json.codeUnits));
    final options = skottie.Options(
      backgroundColor: widget.backgroundColor.value,
      loop: widget.loop,
      autoplay: widget.autoplay,
    );
    _loader.load(Buffer(vmo: vmo, size: vmo.size), options,
        (skottie.Status status, InterfaceHandle<skottie.Player> player) {
      widget.onLoad(status, skottie.PlayerProxy()..ctrl.bind(player));
    });
  }
}
