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

import 'recorder.dart';
import 'test_data.dart';

/// Draws 9 screens worth of text in a 3x3 grid with only the middle cell
/// appearing on the visible screen:
///
///     +-------------+-------------+-------------+
///     |             |             |             |
///     |  invisible  |  invisible  |  invisible  |
///     |             |             |             |
///     +-----------------------------------------+
///     |             |             |             |
///     |  invisible  |   visible   |  invisible  |
///     |             |             |             |
///     +-----------------------------------------+
///     |             |             |             |
///     |  invisible  |  invisible  |  invisible  |
///     |             |             |             |
///     +-------------+-------------+-------------+
///
/// This reproduces the bug where we render more than visible causing
/// performance issues: https://github.com/flutter/flutter/issues/48516
class BenchTextOutOfPictureBounds extends SceneBuilderRecorder {
  BenchTextOutOfPictureBounds() : super(name: benchmarkName) {
    const Color red = Color.fromARGB(255, 255, 0, 0);
    const Color green = Color.fromARGB(255, 0, 255, 0);

    // We don't want paragraph generation and layout to pollute benchmark numbers.
    singleLineParagraphs = generateLaidOutParagraphs(
      paragraphCount: 500,
      minWordCountPerParagraph: 2,
      maxWordCountPerParagraph: 4,
      widthConstraint: window.physicalSize.width / 2,
      color: red,
    );
    multiLineParagraphs = generateLaidOutParagraphs(
      paragraphCount: 50,
      minWordCountPerParagraph: 30,
      maxWordCountPerParagraph: 49,
      widthConstraint: window.physicalSize.width / 2,
      color: green,
    );
  }

  // Use hard-coded seed to make sure the data is stable across benchmark runs.
  static final math.Random _random = math.Random(0);

  static const String benchmarkName = 'text_out_of_picture_bounds';

  List<Paragraph> singleLineParagraphs;
  List<Paragraph> multiLineParagraphs;

  @override
  void onDrawFrame(SceneBuilder sceneBuilder) {
    final PictureRecorder pictureRecorder = PictureRecorder();
    final Canvas canvas = Canvas(pictureRecorder);
    final Size screenSize = window.physicalSize;
    const double padding = 10.0;

    // Fills a single cell with random text.
    void fillCellWithText(List<Paragraph> textSource) {
      canvas.save();
      double topOffset = 0;
      while (topOffset < screenSize.height) {
        final Paragraph paragraph =
            textSource[_random.nextInt(textSource.length)];

        // Give it enough space to make sure it ends up being a single-line paragraph.
        paragraph.layout(ParagraphConstraints(width: screenSize.width / 2));

        canvas.drawParagraph(paragraph, Offset.zero);
        canvas.translate(0, paragraph.height + padding);
        topOffset += paragraph.height + padding;
      }
      canvas.restore();
    }

    // Starting with the top-left cell, fill every cell with text.
    canvas.translate(-screenSize.width, -screenSize.height);
    for (int row = 0; row < 3; row++) {
      canvas.save();
      for (int col = 0; col < 3; col++) {
        canvas.drawRect(
          Offset.zero & screenSize,
          Paint()
            ..style = PaintingStyle.stroke
            ..strokeWidth = 2.0,
        );
        // Fill single-line text.
        fillCellWithText(singleLineParagraphs);

        // Fill multi-line text.
        canvas.save();
        canvas.translate(screenSize.width / 2, 0);
        fillCellWithText(multiLineParagraphs);
        canvas.restore();

        // Shift to next column.
        canvas.translate(screenSize.width, 0);
      }

      // Undo horizontal shift.
      canvas.restore();

      // Shift to next row.
      canvas.translate(0, screenSize.height);
    }

    final Picture picture = pictureRecorder.endRecording();
    sceneBuilder.pushOffset(0.0, 0.0);
    sceneBuilder.addPicture(Offset.zero, picture);
    sceneBuilder.pop();
  }
}
