// 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 '../../common/test_initialization.dart';
import 'helper.dart';

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

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

Future<void> testMain() async {
  setUpUnitTests(
    emulateTesterEnvironment: false,
    setUpTestViewDimensions: false,
  );

  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(domDocument.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);
}
