// 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:html' as html;
import 'dart:js_util' as js_util;

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

import 'package:web_engine_tester/golden_tester.dart';
void main() {
  internalBootstrapBrowserTest(() => testMain);
}

void testMain() async {
  const double screenWidth = 600.0;
  const double screenHeight = 800.0;
  const Rect screenRect = Rect.fromLTWH(0, 0, screenWidth, screenHeight);

  // Commit a recording canvas to a bitmap, and compare with the expected
  Future<void> _checkScreenshot(RecordingCanvas rc, String fileName,
      {Rect region = const Rect.fromLTWH(0, 0, 500, 500),
       double maxDiffRatePercent = 0.0, bool write = false}) async {
    final EngineCanvas engineCanvas = BitmapCanvas(screenRect,
        RenderStrategy());

    rc.endRecording();
    rc.apply(engineCanvas, screenRect);

    // Wrap in <flt-scene> so that our CSS selectors kick in.
    final html.Element sceneElement = html.Element.tag('flt-scene');
    try {
      sceneElement.append(engineCanvas.rootElement);
      html.document.body!.append(sceneElement);
      await matchGoldenFile('$fileName.png', region: region,
          maxDiffRatePercent: maxDiffRatePercent, write: write);
    } finally {
      // The page is reused across tests, so remove the element after taking the
      // Scuba screenshot.
      sceneElement.remove();
    }
  }

  setUp(() async {
    debugEmulateFlutterTesterEnvironment = true;
    await webOnlyInitializePlatform();
    webOnlyFontCollection.debugRegisterTestFonts();
    await webOnlyFontCollection.ensureFontsLoaded();
  });

  test('Blend circles with difference and color', () async {
    final RecordingCanvas rc =
        RecordingCanvas(const Rect.fromLTRB(0, 0, 400, 300));
    rc.save();
    rc.drawRect(
        Rect.fromLTRB(0, 0, 400, 400),
        SurfacePaint()
          ..style = PaintingStyle.fill
          ..color = const Color.fromARGB(255, 255, 255, 255));
    rc.drawCircle(
        Offset(100, 100),
        80.0,
        SurfacePaint()
          ..style = PaintingStyle.fill
          ..color = const Color.fromARGB(128, 255, 0, 0)
          ..blendMode = BlendMode.difference);

    rc.drawCircle(
        Offset(170, 100),
        80.0,
        SurfacePaint()
          ..style = PaintingStyle.fill
          ..blendMode = BlendMode.color
          ..color = const Color.fromARGB(128, 0, 255, 0));

    rc.drawCircle(
        Offset(135, 170),
        80.0,
        SurfacePaint()
          ..style = PaintingStyle.fill
          ..color = const Color.fromARGB(128, 255, 0, 0));
    rc.restore();
    await _checkScreenshot(rc, 'canvas_blend_circle_diff_color',
        maxDiffRatePercent: operatingSystem == OperatingSystem.macOs ? 2.95 :
            operatingSystem == OperatingSystem.iOs ? 1.0 : 0);
  });

  test('Blend circle and text with multiply', () async {
    final RecordingCanvas rc =
        RecordingCanvas(const Rect.fromLTRB(0, 0, 400, 300));
    rc.save();
    rc.drawRect(
        Rect.fromLTRB(0, 0, 400, 400),
        SurfacePaint()
          ..style = PaintingStyle.fill
          ..color = const Color.fromARGB(255, 255, 255, 255));
    rc.drawCircle(
        Offset(100, 100),
        80.0,
        SurfacePaint()
          ..style = PaintingStyle.fill
          ..color = const Color.fromARGB(128, 255, 0, 0)
          ..blendMode = BlendMode.difference);
    rc.drawCircle(
        Offset(170, 100),
        80.0,
        SurfacePaint()
          ..style = PaintingStyle.fill
          ..blendMode = BlendMode.color
          ..color = const Color.fromARGB(128, 0, 255, 0));

    rc.drawCircle(
        Offset(135, 170),
        80.0,
        SurfacePaint()
          ..style = PaintingStyle.fill
          ..color = const Color.fromARGB(128, 255, 0, 0));
    rc.drawImage(createTestImage(), Offset(135.0, 130.0),
        SurfacePaint()..blendMode = BlendMode.multiply);
    rc.restore();
    await _checkScreenshot(rc, 'canvas_blend_image_multiply',
        maxDiffRatePercent: operatingSystem == OperatingSystem.macOs ? 2.95 :
        operatingSystem == OperatingSystem.iOs ? 2.0 : 0);
  });
}

HtmlImage createTestImage() {
  const int width = 100;
  const int height = 50;
  html.CanvasElement canvas =
      new html.CanvasElement(width: width, height: height);
  html.CanvasRenderingContext2D ctx = canvas.context2D;
  ctx.fillStyle = '#E04040';
  ctx.fillRect(0, 0, 33, 50);
  ctx.fill();
  ctx.fillStyle = '#40E080';
  ctx.fillRect(33, 0, 33, 50);
  ctx.fill();
  ctx.fillStyle = '#2040E0';
  ctx.fillRect(66, 0, 33, 50);
  ctx.fill();
  html.ImageElement imageElement = html.ImageElement();
  imageElement.src = js_util.callMethod(canvas, 'toDataURL', <dynamic>[]);
  return HtmlImage(imageElement, width, height);
}
