// 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:ui';

import 'package:macrobenchmarks/src/web/recorder.dart';

/// Measure the performance of paint bounds estimation by recording a picture
/// without actually rendering it.
///
/// Bounds estimation is done in two phases:
///
/// * As we call drawing methods on `Canvas` we grow bounds with every paint op.
/// * When we're done recording a picture we call `PictureRecorder.endRecording`
///   at which point we compute the overall picture bounds and cache the result.
///
/// This benchmarks puts emphasis on paint operations that trigger expensive
/// math such as `transformLTRB`. To do that we push non-identity transforms
/// and rotations before calling drawing methods.
class BenchPictureRecording extends RawRecorder {
  BenchPictureRecording() : super(name: benchmarkName);

  static const String benchmarkName = 'bench_picture_recording';

  /// Cached paint used for drawing.
  ///
  /// We want to avoid polluting the results with paint initialization logic.
  Paint paint;

  /// A prelaid out and cached paragraph.
  ///
  /// This is cached to remove text layout time from the benchmark time.
  Paragraph paragraph;

  @override
  Future<void> setUpAll() async {
    paint = Paint();
    paragraph = (ParagraphBuilder(ParagraphStyle())
        ..addText('abcd edfh ijkl mnop qrst uvwx yz'))
      .build()
        ..layout(const ParagraphConstraints(width: 50));
  }

  @override
  void body(Profile profile) {
    final PictureRecorder recorder = PictureRecorder();
    final Canvas canvas = Canvas(recorder);
    profile.record('recordPaintCommands', () {
      for (int i = 1; i <= 100; i++) {
        canvas.translate((10 + i).toDouble(), (10 + i).toDouble());

        canvas.save();
        for (int j = 0; j < 10; j++) {
          canvas.drawRect(const Rect.fromLTWH(10, 10, 10, 10), paint);
          canvas.drawCircle(const Offset(50, 50), 50, paint);
          canvas.rotate(1.0);
        }
        canvas.restore();

        canvas.save();
        for (int j = 0; j < 10; j++) {
          canvas.translate(1, 1);
          canvas.clipRect(Rect.fromLTWH(20, 20, 40 / i, 40));
          canvas.drawRRect(RRect.fromRectAndRadius(const Rect.fromLTWH(10, 10, 10, 10), const Radius.circular(2)), paint);
          canvas.drawParagraph(paragraph, Offset.zero);
        }
        canvas.restore();
      }
    }, reported: true);
    profile.record('estimatePaintBounds', () {
      recorder.endRecording();
    }, reported: true);
  }
}
