// Copyright 2014 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.

/// @docImport 'package:flutter/material.dart';
///
/// @docImport 'goldens.dart';
/// @docImport 'widget_tester.dart';
library;

import 'dart:ui' as ui;

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';

// A Future<ui.Image> that stores the resolved result.
class _AsyncImage {
  _AsyncImage(Future<ui.Image> task) {
    _task = task.then((ui.Image image) {
      _result = image;
    });
  }

  // Returns the resolved image.
  Future<ui.Image> result() async {
    if (_result != null) {
      return _result!;
    }
    await _task;
    assert(_result != null);
    return _result!;
  }

  late final Future<void> _task;
  ui.Image? _result;

  // Wait for a list of `_AsyncImage` and returns the list of its resolved
  // images.
  static Future<List<ui.Image>> resolveList(List<_AsyncImage> targets) {
    final Iterable<Future<ui.Image>> images = targets.map<Future<ui.Image>>(
        (_AsyncImage target) => target.result());
    return Future.wait<ui.Image>(images);
  }
}

/// Records the frames of an animating widget, and later displays the frames as a
/// grid in an animation sheet.
///
/// This class does not support Web, because the animation sheet utilizes taking
/// screenshots, which is unsupported on the Web. Tests that use this class must
/// be noted with `skip: isBrowser`.
/// (https://github.com/flutter/flutter/issues/56001)
///
/// Using this class includes the following steps:
///
///  * Create an instance of this class.
///  * Register [dispose] to the test's tear down callbacks.
///  * Pump frames that render the target widget wrapped in [record]. Every frame
///    that has `recording` being true will be recorded.
///  * Acquire the output image with [collate] and compare against the golden
///    file.
///
/// {@tool snippet}
/// The following example shows how to record an animation sheet of an [InkWell]
/// being pressed then released.
///
/// ```dart
/// testWidgets('Inkwell animation sheet', (WidgetTester tester) async {
///   // Create instance
///   final AnimationSheetBuilder animationSheet = AnimationSheetBuilder(frameSize: const Size(48, 24));
///   addTearDown(animationSheet.dispose);
///
///   final Widget target = Material(
///     child: Directionality(
///       textDirection: TextDirection.ltr,
///       child: InkWell(
///         splashColor: Colors.blue,
///         onTap: () {},
///       ),
///     ),
///   );
///
///   // Optional: setup before recording (`recording` is false)
///   await tester.pumpWidget(animationSheet.record(
///     target,
///     recording: false,
///   ));
///
///   final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(InkWell)));
///
///   // Start recording (`recording` is true)
///   await tester.pumpFrames(animationSheet.record(
///     target,
///     recording: true, // ignore: avoid_redundant_argument_values
///   ), const Duration(seconds: 1));
///
///   await gesture.up();
///
///   await tester.pumpFrames(animationSheet.record(
///     target,
///     recording: true, // ignore: avoid_redundant_argument_values
///   ), const Duration(seconds: 1));
///
///   // Compare against golden file
///   await expectLater(
///     animationSheet.collate(800),
///     matchesGoldenFile('inkwell.press.animation.png'),
///   );
/// }, skip: isBrowser); // Animation sheet does not support browser https://github.com/flutter/flutter/issues/56001
/// ```
/// {@end-tool}
///
/// See also:
///
///  * [GoldenFileComparator], which introduces Golden File Testing.
class AnimationSheetBuilder {
  /// Starts a session of building an animation sheet.
  ///
  /// The [frameSize] is a tight constraint for the child to be recorded, and must not
  /// be null.
  ///
  /// The [allLayers] controls whether to record elements drawn out of the subtree,
  /// and defaults to false.
  AnimationSheetBuilder({
    required this.frameSize,
    this.allLayers = false,
  }) : assert(!kIsWeb);

  /// Dispose all recorded frames and result images.
  ///
  /// This method must be called before the test case ends (usually as a tear
  /// down callback) to properly deallocate the images.
  ///
  /// After this method is called, there will be no frames to [collate].
  Future<void> dispose() async {
    final List<_AsyncImage> targets = <_AsyncImage>[
      ..._recordedFrames,
      ..._results,
    ];
    _recordedFrames.clear();
    _results.clear();
    for (final ui.Image image in await _AsyncImage.resolveList(targets)) {
      image.dispose();
    }
  }

  /// The size of the child to be recorded.
  ///
  /// This size is applied as a tight layout constraint for the child, and is
  /// fixed throughout the building session.
  final Size frameSize;

  /// Whether the captured image comes from the entire tree, or only the
  /// subtree of [record].
  ///
  /// If [allLayers] is false, then the [record] widget will capture the image
  /// composited by its subtree. If [allLayers] is true, then the [record] will
  /// capture the entire tree composited and clipped by [record]'s region.
  ///
  /// The two modes are identical if there is nothing in front of [record].
  /// But in rare cases, what needs to be captured has to be rendered out of
  /// [record]'s subtree in its front. By setting [allLayers] to true, [record]
  /// captures everything within its region even if drawn outside of its
  /// subtree.
  ///
  /// Defaults to false.
  final bool allLayers;

  final List<_AsyncImage> _recordedFrames = <_AsyncImage>[];

  /// Returns a widget that renders a widget in a box that can be recorded.
  ///
  /// The returned widget wraps `child` in a box with a fixed size specified by
  /// [frameSize]. The `key` is also applied to the returned widget.
  ///
  /// The frame is only recorded if the `recording` argument is true, or during
  /// a procedure that is wrapped within [recording]. In either case, the
  /// painted result of each frame will be stored and later available for
  /// [collate]. If neither condition is met, the frames are not recorded, which
  /// is useful during setup phases.
  ///
  /// See also:
  ///
  ///  * [WidgetTester.pumpFrames], which renders a widget in a series of frames
  ///    with a fixed time interval.
  Widget record(Widget child, {
    Key? key,
    bool recording = true,
  }) {
    return _AnimationSheetRecorder(
      key: key,
      size: frameSize,
      allLayers: allLayers,
      handleRecorded: !recording ? null : (Future<ui.Image> futureImage) {
        _recordedFrames.add(_AsyncImage(() async {
          final ui.Image image = await futureImage;
          assert(image.width == frameSize.width && image.height == frameSize.height,
            'Unexpected size mismatch: frame has (${image.width}, ${image.height}) '
            'while `frameSize` is $frameSize.'
          );
          return image;
        }()));
      },
      child: child,
    );
  }

  // The result images generated by `collate`.
  //
  // They're stored here to be disposed by [dispose].
  final List<_AsyncImage> _results = <_AsyncImage>[];

  /// Returns an result image by putting all frames together in a table.
  ///
  /// This method returns an image that arranges the captured frames in a table,
  /// which has `cellsPerRow` images per row with the order from left to right,
  /// top to bottom.
  ///
  /// The result image of this method is managed by [AnimationSheetBuilder],
  /// and should not be disposed by the caller.
  ///
  /// An example of using this method can be found at [AnimationSheetBuilder].
  Future<ui.Image> collate(int cellsPerRow) async {
    assert(_recordedFrames.isNotEmpty,
      'No frames are collected. Have you forgot to set `recording` to true?');
    final _AsyncImage result = _AsyncImage(_collateFrames(_recordedFrames, frameSize, cellsPerRow));
    _results.add(result);
    return result.result();
  }
}

typedef _RecordedHandler = void Function(Future<ui.Image> image);

class _AnimationSheetRecorder extends StatefulWidget {
  const _AnimationSheetRecorder({
    this.handleRecorded,
    required this.child,
    required this.size,
    required this.allLayers,
    super.key,
  });

  final _RecordedHandler? handleRecorded;
  final Widget child;
  final Size size;
  final bool allLayers;

  @override
  State<StatefulWidget> createState() => _AnimationSheetRecorderState();
}

class _AnimationSheetRecorderState extends State<_AnimationSheetRecorder> {
  GlobalKey boundaryKey = GlobalKey();

  void _record(Duration duration) {
    assert(widget.handleRecorded != null);
    final _RenderRootableRepaintBoundary boundary = boundaryKey.currentContext!.findRenderObject()! as _RenderRootableRepaintBoundary;
    if (widget.allLayers) {
      widget.handleRecorded!(boundary.allLayersToImage());
    } else {
      widget.handleRecorded!(boundary.toImage());
    }
  }

  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.topLeft,
      child: SizedBox.fromSize(
        size: widget.size,
        child: _RootableRepaintBoundary(
          key: boundaryKey,
          child: _PostFrameCallbacker(
            callback: widget.handleRecorded == null ? null : _record,
            child: widget.child,
          ),
        ),
      ),
    );
  }
}

// Invokes `callback` and [markNeedsPaint] during the post-frame callback phase
// of every frame.
//
// If `callback` is non-null, `_PostFrameCallbacker` adds a post-frame callback
// every time it paints, during which it calls the provided `callback` then
// invokes [markNeedsPaint].
//
// If `callback` is null, `_PostFrameCallbacker` is equivalent to a proxy box.
class _PostFrameCallbacker extends SingleChildRenderObjectWidget {
  const _PostFrameCallbacker({
    super.child,
    this.callback,
  });

  final FrameCallback? callback;

  @override
  _RenderPostFrameCallbacker createRenderObject(BuildContext context) => _RenderPostFrameCallbacker(
    callback: callback,
  );

  @override
  void updateRenderObject(BuildContext context, _RenderPostFrameCallbacker renderObject) {
    renderObject.callback = callback;
  }
}

class _RenderPostFrameCallbacker extends RenderProxyBox {
  _RenderPostFrameCallbacker({
    FrameCallback? callback,
  }) : _callback = callback;

  FrameCallback? get callback => _callback;
  FrameCallback? _callback;
  set callback(FrameCallback? value) {
    _callback = value;
    if (value != null) {
      markNeedsPaint();
    }
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    if (callback != null) {
      SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
        callback!(duration);
        markNeedsPaint();
      });
    }
    super.paint(context, offset);
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(FlagProperty('callback', value: callback != null, ifTrue: 'has a callback'));
  }
}

Future<ui.Image> _collateFrames(List<_AsyncImage> futureFrames, Size frameSize, int cellsPerRow) async {
  final List<ui.Image> frames = await _AsyncImage.resolveList(futureFrames);
  final int rowNum = (frames.length / cellsPerRow).ceil();

  final ui.PictureRecorder recorder = ui.PictureRecorder();
  final Canvas canvas = Canvas(
    recorder,
    Rect.fromLTWH(0, 0, frameSize.width * cellsPerRow, frameSize.height * rowNum),
  );
  for (int i = 0; i < frames.length; i += 1) {
    canvas.drawImage(
      frames[i],
      Offset(frameSize.width * (i % cellsPerRow), frameSize.height * (i / cellsPerRow).floor()),
      Paint(),
    );
  }
  final ui.Picture picture = recorder.endRecording();
  final ui.Image image = await picture.toImage(
    (frameSize.width * cellsPerRow).toInt(),
    (frameSize.height * rowNum).toInt(),
  );
  picture.dispose();
  return image;
}

class _RenderRootableRepaintBoundary extends RenderRepaintBoundary {
  // Like [toImage], but captures an image of all layers (composited by
  // RenderView and its children) clipped by the region of this object.
  Future<ui.Image> allLayersToImage() {
    final TransformLayer rootLayer = _rootLayer();
    final Matrix4 rootTransform = (rootLayer.transform ?? Matrix4.identity()).clone();
    final Matrix4 transform = rootTransform.multiplied(getTransformTo(null));
    final Rect rect = MatrixUtils.transformRect(transform, Offset.zero & size);
    // The scale was used to fit the actual device. Revert it since the target
    // is the logical display. Take transform[0] as the scale.
    return rootLayer.toImage(rect, pixelRatio: 1 / transform[0]);
  }

  TransformLayer _rootLayer() {
    Layer layer = this.layer!;
    while (layer.parent != null) {
      layer = layer.parent!;
    }
    return layer as TransformLayer;
  }
}

// A [RepaintBoundary], except that its render object has a `fullscreenToImage` method.
class _RootableRepaintBoundary extends SingleChildRenderObjectWidget {
  /// Creates a widget that isolates repaints.
  const _RootableRepaintBoundary({ super.key, super.child });

  @override
  _RenderRootableRepaintBoundary createRenderObject(BuildContext context) => _RenderRootableRepaintBoundary();
}
