// Copyright 2013 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:async';

import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' hide window;

import 'helper.dart';
import 'text_scuba.dart';

typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);

const Rect bounds = Rect.fromLTWH(0, 0, 800, 600);

void main() {
  internalBootstrapBrowserTest(() => testMain);
}

Future<void> testMain() async {
  setUpStableTestFonts();

  test('draws paragraphs with placeholders', () {
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());

    Offset offset = Offset.zero;
    for (final PlaceholderAlignment placeholderAlignment in PlaceholderAlignment.values) {
      final CanvasParagraph paragraph = rich(
        EngineParagraphStyle(fontFamily: 'Roboto', fontSize: 14.0),
        (CanvasParagraphBuilder builder) {
          builder.pushStyle(TextStyle(color: black));
          builder.addText('Lorem ipsum');
          builder.addPlaceholder(
            80.0,
            50.0,
            placeholderAlignment,
            baselineOffset: 40.0,
            baseline: TextBaseline.alphabetic,
          );
          builder.pushStyle(TextStyle(color: blue));
          builder.addText('dolor sit amet, consecteur.');
        },
      )..layout(constrain(200.0));

      // Draw the paragraph.
      canvas.drawParagraph(paragraph, offset);

      // Then fill the placeholders.
      fillPlaceholder(canvas, offset, paragraph);

      offset = offset.translate(0.0, paragraph.height + 30.0);
    }

    return takeScreenshot(canvas, bounds, 'canvas_paragraph_placeholders');
  });

  test('draws paragraphs with placeholders and text align', () {
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());

    const List<TextAlign> aligns = <TextAlign>[
      TextAlign.left,
      TextAlign.center,
      TextAlign.right,
    ];

    Offset offset = Offset.zero;
    for (final TextAlign align in aligns) {
      final CanvasParagraph paragraph = rich(
        EngineParagraphStyle(fontFamily: 'Roboto', fontSize: 14.0, textAlign: align),
        (CanvasParagraphBuilder builder) {
          builder.pushStyle(TextStyle(color: black));
          builder.addText('Lorem');
          builder.addPlaceholder(80.0, 50.0, PlaceholderAlignment.bottom);
          builder.pushStyle(TextStyle(color: blue));
          builder.addText('ipsum.');
        },
      )..layout(constrain(200.0));

      // Draw the paragraph.
      canvas.drawParagraph(paragraph, offset);

      // Then fill the placeholders.
      fillPlaceholder(canvas, offset, paragraph);

      offset = offset.translate(0.0, paragraph.height + 30.0);
    }

    return takeScreenshot(canvas, bounds, 'canvas_paragraph_placeholders_align');
  });

  test('draws paragraphs with placeholders and text align in DOM mode', () {
    final DomCanvas canvas = DomCanvas(domRenderer.createElement('flt-picture'));

    const List<TextAlign> aligns = <TextAlign>[
      TextAlign.left,
      TextAlign.center,
      TextAlign.right,
    ];

    Offset offset = Offset.zero;
    for (final TextAlign align in aligns) {
      final CanvasParagraph paragraph = rich(
        EngineParagraphStyle(fontFamily: 'Roboto', fontSize: 14.0, textAlign: align),
        (CanvasParagraphBuilder builder) {
          builder.pushStyle(TextStyle(color: black));
          builder.addText('Lorem');
          builder.addPlaceholder(80.0, 50.0, PlaceholderAlignment.bottom);
          builder.pushStyle(TextStyle(color: blue));
          builder.addText('ipsum.');
        },
      )..layout(constrain(200.0));

      // Draw the paragraph.
      canvas.drawParagraph(paragraph, offset);

      // Then fill the placeholders.
      fillPlaceholder(canvas, offset, paragraph);

      offset = offset.translate(0.0, paragraph.height + 30.0);
    }

    return takeScreenshot(canvas, bounds, 'canvas_paragraph_placeholders_align_dom');
  });

  test('draws paragraphs starting or ending with a placeholder', () {
    const Rect bounds = Rect.fromLTWH(0, 0, 420, 300);
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());

    Offset offset = const Offset(10, 10);

    // First paragraph with a placeholder at the beginning.
    final CanvasParagraph paragraph1 = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', fontSize: 24.0, textAlign: TextAlign.center),
      (CanvasParagraphBuilder builder) {
        builder.addPlaceholder(80.0, 50.0, PlaceholderAlignment.baseline, baseline: TextBaseline.alphabetic);
        builder.pushStyle(TextStyle(color: black));
        builder.addText(' Lorem ipsum.');
      },
    )..layout(constrain(400.0));

    // Draw the paragraph.
    canvas.drawParagraph(paragraph1, offset);
    fillPlaceholder(canvas, offset, paragraph1);
    surroundParagraph(canvas, offset, paragraph1);

    offset = offset.translate(0.0, paragraph1.height + 30.0);

    // Second paragraph with a placeholder at the end.
    final CanvasParagraph paragraph2 = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', fontSize: 24.0, textAlign: TextAlign.center),
      (CanvasParagraphBuilder builder) {
        builder.pushStyle(TextStyle(color: black));
        builder.addText('Lorem ipsum ');
        builder.addPlaceholder(80.0, 50.0, PlaceholderAlignment.baseline, baseline: TextBaseline.alphabetic);
      },
    )..layout(constrain(400.0));

    // Draw the paragraph.
    canvas.drawParagraph(paragraph2, offset);
    fillPlaceholder(canvas, offset, paragraph2);
    surroundParagraph(canvas, offset, paragraph2);

    offset = offset.translate(0.0, paragraph2.height + 30.0);

    // Third paragraph with a placeholder alone in the second line.
    final CanvasParagraph paragraph3 = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', fontSize: 24.0, textAlign: TextAlign.center),
      (CanvasParagraphBuilder builder) {
        builder.pushStyle(TextStyle(color: black));
        builder.addText('Lorem ipsum ');
        builder.addPlaceholder(80.0, 50.0, PlaceholderAlignment.baseline, baseline: TextBaseline.alphabetic);
      },
    )..layout(constrain(200.0));

    // Draw the paragraph.
    canvas.drawParagraph(paragraph3, offset);
    fillPlaceholder(canvas, offset, paragraph3);
    surroundParagraph(canvas, offset, paragraph3);

    return takeScreenshot(canvas, bounds, 'canvas_paragraph_placeholders_start_and_end');
  });
}

void surroundParagraph(
  EngineCanvas canvas,
  Offset offset,
  CanvasParagraph paragraph,
) {
  final Rect rect = offset & Size(paragraph.width, paragraph.height);
  final SurfacePaint paint = SurfacePaint()..color = blue..style = PaintingStyle.stroke;
  canvas.drawRect(rect, paint.paintData);
}

void fillPlaceholder(
  EngineCanvas canvas,
  Offset offset,
  CanvasParagraph paragraph,
) {
  final TextBox placeholderBox = paragraph.getBoxesForPlaceholders().single;
  final SurfacePaint paint = SurfacePaint()..color = red;
  canvas.drawRect(placeholderBox.toRect().shift(offset), paint.paintData);
}
