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

import 'dart:math' as math;
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';

/// 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.
///  * 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));
///
///   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,
///   ), const Duration(seconds: 1));
///
///   await gesture.up();
///
///   await tester.pumpFrames(animationSheet.record(
///     target,
///     recording: true,
///   ), 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), // Does not support Web. See [AnimationSheetBuilder].
       assert(frameSize != null);

  /// 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<Future<ui.Image>> _recordedFrames = <Future<ui.Image>>[];
  Future<List<ui.Image>> get _frames async {
    final List<ui.Image> frames = await Future.wait<ui.Image>(_recordedFrames, eagerError: true);
    assert(() {
      for (final ui.Image frame in frames) {
        assert(frame.width == frameSize.width && frame.height == frameSize.height,
          'Unexpected size mismatch: frame has (${frame.width}, ${frame.height}) '
          'while `frameSize` is $frameSize.'
        );
      }
      return true;
    }());
    return frames;
  }

  /// 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 `recording` defaults to true, which means the painted result of each
  /// frame will be stored and later available for [display]. If `recording` is
  /// false, then frames are not recorded. This is useful during the setup phase
  /// that shouldn't be recorded; if the target widget isn't wrapped in [record]
  /// during the setup phase, the states will be lost when it starts recording.
  ///
  /// The `child` must not be null.
  ///
  /// 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,
  }) {
    assert(child != null);
    return _AnimationSheetRecorder(
      key: key,
      size: frameSize,
      allLayers: allLayers,
      handleRecorded: recording ? _recordedFrames.add : null,
      child: child,
    );
  }

  /// Constructs a widget that renders the recorded frames in an animation sheet.
  ///
  /// The resulting widget takes as much space as its parent allows, which is
  /// usually the screen size. It is then filled with all recorded frames, each
  /// having a size specified by [frameSize], chronologically from top-left to
  /// bottom-right in a row-major order.
  ///
  /// This widget does not check whether its size fits all recorded frames.
  /// Having too many frames can cause overflow errors, while having too few can
  /// waste the size of golden files. Therefore you should usually adjust the
  /// viewport size to [sheetSize] before calling this method.
  ///
  /// The `key` is applied to the root widget.
  ///
  /// This method can only be called if at least one frame has been recorded.
  ///
  /// The [display] is the legacy way of acquiring the output for comparison.
  /// It is not recommended because it requires more boilerplate, and produces
  /// a much large image than necessary: each pixel is rendered in 3x3 pixels
  /// without higher definition. Use [collate] instead.
  ///
  /// Using this way includes the following steps:
  ///
  ///  * Create an instance of this class.
  ///  * Pump frames that render the target widget wrapped in [record]. Every frame
  ///    that has `recording` being true will be recorded.
  ///  * Adjust the size of the test viewport to the [sheetSize] (see the
  ///    documentation of [sheetSize] for more information).
  ///  * Pump a frame that renders [display], which shows all recorded frames in an
  ///    animation sheet, and can be matched against the golden test.
  ///
  /// {@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));
  ///
  ///   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,
  ///   ), const Duration(seconds: 1));
  ///
  ///   await gesture.up();
  ///
  ///   await tester.pumpFrames(animationSheet.record(
  ///     target,
  ///     recording: true,
  ///   ), const Duration(seconds: 1));
  ///
  ///   // Adjust view port size
  ///   tester.binding.setSurfaceSize(animationSheet.sheetSize());
  ///
  ///   // Display
  ///   final Widget display = await animationSheet.display();
  ///   await tester.pumpWidget(display);
  ///
  ///   // Compare against golden file
  ///   await expectLater(
  ///     find.byWidget(display),
  ///     matchesGoldenFile('inkwell.press.animation.png'),
  ///   );
  /// }, skip: isBrowser); // Animation sheet does not support browser https://github.com/flutter/flutter/issues/56001
  /// ```
  /// {@end-tool}
  @Deprecated(
    'Use AnimationSheetBuilder.collate instead. '
    'This feature was deprecated after v2.3.0-13.0.pre.',
  )
  Future<Widget> display({Key? key}) async {
    assert(_recordedFrames.isNotEmpty);
    final List<ui.Image> frames = await _frames;
    return _CellSheet(
      key: key,
      cellSize: frameSize,
      children: frames.map((ui.Image image) => RawImage(
        image: image.clone(),
        width: frameSize.width,
        height: frameSize.height,
        // Disable quality enhancement because the point of this class is to
        // precisely record what the widget looks like.
        filterQuality: ui.FilterQuality.none,
      )).toList(),
    );
  }

  /// Returns an result image by putting all frames together in a table.
  ///
  /// This method returns a table of captured frames, `cellsPerRow` images
  /// per row, from left to right, top to bottom.
  ///
  /// An example of using this method can be found at [AnimationSheetBuilder].
  Future<ui.Image> collate(int cellsPerRow) async {
    return _collateFrames(await _frames, frameSize, cellsPerRow);
  }

  /// Returns the smallest size that can contain all recorded frames.
  ///
  /// This is used to adjust the viewport during unit tests, i.e. the size of
  /// virtual screen. Having too many frames recorded than the default viewport
  /// size can contain will lead to overflow errors, while having too few frames
  /// means the golden file might be larger than necessary.
  ///
  /// The [sheetSize] returns the smallest possible size by placing the
  /// recorded frames, each of which has a size specified by [frameSize], in a
  /// row-major grid with a maximum width specified by `maxWidth`, and returns
  /// the size of that grid.
  ///
  /// Setting the viewport size during a widget test usually involves
  /// [TestWidgetsFlutterBinding.setSurfaceSize] and [WidgetTester.binding].
  ///
  /// The `maxWidth` defaults to the width of the default viewport, 800.0.
  ///
  /// This method can only be called if at least one frame has been recorded.
  @Deprecated(
    'The `sheetSize` is only useful for `display`, which should be migrated to `collate`. '
    'This feature was deprecated after v2.3.0-13.0.pre.',
  )
  Size sheetSize({double maxWidth = _kDefaultTestViewportWidth}) {
    assert(_recordedFrames.isNotEmpty);
    final int cellsPerRow = (maxWidth / frameSize.width).floor();
    final int rowNum = (_recordedFrames.length / cellsPerRow).ceil();
    final double width = math.min(cellsPerRow, _recordedFrames.length) * frameSize.width;
    return Size(width, frameSize.height * rowNum);
  }

  // The width of _kDefaultTestViewportSize in [TestViewConfiguration].
  static const double _kDefaultTestViewportWidth = 800.0;
}

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,
    Key? key,
  }) : super(key: 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({
    Key? key,
    Widget? child,
    this.callback,
  }) : super(key: key, child: child);

  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<ui.Image> frames, Size frameSize, int cellsPerRow) async {
  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(),
    );
  }
  return recorder.endRecording().toImage(
    (frameSize.width * cellsPerRow).toInt(),
    (frameSize.height * rowNum).toInt(),
  );
}

// Layout children in a grid of fixed-sized cells.
//
// The sheet fills up as much space as the parent allows. The cells are
// positioned from top left to bottom right in a row-major order.
class _CellSheet extends StatelessWidget {
  _CellSheet({
    Key? key,
    required this.cellSize,
    required this.children,
  }) : assert(cellSize != null),
       assert(children != null && children.isNotEmpty),
       super(key: key);

  final Size cellSize;
  final List<Widget> children;

  @override
  Widget build(BuildContext _context) {
    return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
      final double rowWidth = constraints.biggest.width;
      final int cellsPerRow = (rowWidth / cellSize.width).floor();
      final List<Widget> rows = <Widget>[];
      for (int rowStart = 0; rowStart < children.length; rowStart += cellsPerRow) {
        final Iterable<Widget> rowTargets = children.sublist(rowStart, math.min(rowStart + cellsPerRow, children.length));
        rows.add(Row(
          textDirection: TextDirection.ltr,
          children: rowTargets.map((Widget target) => SizedBox.fromSize(
            size: cellSize,
            child: target,
          )).toList(),
        ));
      }
      return Column(
        textDirection: TextDirection.ltr,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: rows,
      );
    });
  }
}

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({ Key? key, Widget? child }) : super(key: key, child: child);

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