// 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 = _generateParagraphs(
      paragraphCount: 500,
      minWordCountPerParagraph: 2,
      maxWordCountPerParagraph: 5,
      color: red,
    );
    multiLineParagraphs = _generateParagraphs(
      paragraphCount: 50,
      minWordCountPerParagraph: 30,
      maxWordCountPerParagraph: 50,
      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();
  }

  /// Generates strings and builds pre-laid out paragraphs to be used by the
  /// benchmark.
  List<Paragraph> _generateParagraphs({
    int paragraphCount,
    int minWordCountPerParagraph,
    int maxWordCountPerParagraph,
    Color color,
  }) {
    final List<Paragraph> strings = <Paragraph>[];
    int wordPointer = 0; // points to the next word in lipsum to extract
    for (int i = 0; i < paragraphCount; i++) {
      final int wordCount = minWordCountPerParagraph +
          _random.nextInt(maxWordCountPerParagraph - minWordCountPerParagraph);
      final List<String> string = <String>[];
      for (int j = 0; j < wordCount; j++) {
        string.add(lipsum[wordPointer]);
        wordPointer = (wordPointer + 1) % lipsum.length;
      }

      final ParagraphBuilder builder =
          ParagraphBuilder(ParagraphStyle(fontFamily: 'sans-serif'))
            ..pushStyle(TextStyle(color: color, fontSize: 18.0))
            ..addText(string.join(' '))
            ..pop();
      final Paragraph paragraph = builder.build();

      // Fill half the screen.
      paragraph
          .layout(ParagraphConstraints(width: window.physicalSize.width / 2));
      strings.add(paragraph);
    }
    return strings;
  }
}
