// 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 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart' hide BackdropFilterEngineLayer, ClipRectEngineLayer;
import 'package:ui/ui.dart';

import 'package:web_engine_tester/golden_tester.dart';

import '../../common/test_initialization.dart';

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

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

  setUp(() async {
    debugShowClipLayers = true;
    SurfaceSceneBuilder.debugForgetFrameScene();
    for (final DomNode scene in domDocument.querySelectorAll('flt-scene')) {
      scene.remove();
    }
  });

  // The black circle on the left should not be blurred since it is outside
  // the clip boundary around backdrop filter. However there should be only
  // one red dot since the other one should be blurred by filter.
  test('Background should only blur at ancestor clip boundary', () async {
    const Rect region = Rect.fromLTWH(0, 0, 190, 130);

    final SurfaceSceneBuilder builder = SurfaceSceneBuilder();
    final Picture backgroundPicture = _drawBackground(region);
    builder.addPicture(Offset.zero, backgroundPicture);

    builder.pushClipRect(
      const Rect.fromLTRB(10, 10, 180, 120),
    );
    final Picture circles1 = _drawTestPictureWithCircles(region, 30, 30);
    builder.addPicture(Offset.zero, circles1);

    builder.pushClipRect(
      const Rect.fromLTRB(60, 10, 180, 120),
    );
    builder.pushBackdropFilter(ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0));
    final Picture circles2 = _drawTestPictureWithCircles(region, 90, 30);
    builder.addPicture(Offset.zero, circles2);
    builder.pop();
    builder.pop();
    builder.pop();

    domDocument.body!.append(builder
        .build()
        .webOnlyRootElement!);

    await matchGoldenFile('backdrop_filter_clip.png', region: region);
  });

  test('Background should only blur at ancestor clip boundary after move', () async {
    const Rect region = Rect.fromLTWH(0, 0, 190, 130);

    final SurfaceSceneBuilder builder = SurfaceSceneBuilder();
    final Picture backgroundPicture = _drawBackground(region);
    builder.addPicture(Offset.zero, backgroundPicture);
    final ClipRectEngineLayer clipEngineLayer = builder.pushClipRect(
      const Rect.fromLTRB(10, 10, 180, 120),
    );
    final Picture circles1 = _drawTestPictureWithCircles(region, 30, 30);
    builder.addPicture(Offset.zero, circles1);
    final ClipRectEngineLayer clipEngineLayer2 = builder.pushClipRect(
      const Rect.fromLTRB(60, 10, 180, 120),
    );
    final BackdropFilterEngineLayer oldBackdropFilterLayer =
        builder.pushBackdropFilter(ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0));
    final Picture circles2 = _drawTestPictureWithCircles(region, 90, 30);
    builder.addPicture(Offset.zero, circles2);
    builder.pop();
    builder.pop();
    builder.pop();
    builder.build();

    // Now reparent filter layer in next scene.
    final SurfaceSceneBuilder builder2 = SurfaceSceneBuilder();
    builder2.addPicture(Offset.zero, backgroundPicture);
    builder2.pushClipRect(
      const Rect.fromLTRB(10, 10, 180, 120),
      oldLayer: clipEngineLayer
    );
    builder2.addPicture(Offset.zero, circles1);
    builder2.pushClipRect(
      const Rect.fromLTRB(10, 75, 180, 120),
      oldLayer: clipEngineLayer2
    );
    builder2.pushBackdropFilter(ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
        oldLayer: oldBackdropFilterLayer);
    builder2.addPicture(Offset.zero, circles2);
    builder2.pop();
    builder2.pop();
    builder2.pop();

    domDocument.body!.append(builder2
        .build()
        .webOnlyRootElement!);

    await matchGoldenFile('backdrop_filter_clip_moved.png', region: region);
  });

  // The blur filter should be applied to the background inside the clip even
  // though there are no children of the backdrop filter.
  test('Background should blur even if child does not paint', () async {
    const Rect region = Rect.fromLTWH(0, 0, 190, 130);

    final SurfaceSceneBuilder builder = SurfaceSceneBuilder();
    final Picture backgroundPicture = _drawBackground(region);
    builder.addPicture(Offset.zero, backgroundPicture);

    builder.pushClipRect(
      const Rect.fromLTRB(10, 10, 180, 120),
    );
    final Picture circles1 = _drawTestPictureWithCircles(region, 30, 30);
    builder.addPicture(Offset.zero, circles1);

    builder.pushClipRect(
      const Rect.fromLTRB(60, 10, 180, 120),
    );
    builder.pushBackdropFilter(ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0));
    builder.pop();
    builder.pop();
    builder.pop();

    domDocument.body!.append(builder
        .build()
        .webOnlyRootElement!);

    await matchGoldenFile('backdrop_filter_no_child_rendering.png',
        region: region);
  });
  test('colorFilter as imageFilter', () async {
    const Rect region = Rect.fromLTWH(0, 0, 190, 130);

    final SurfaceSceneBuilder builder = SurfaceSceneBuilder();
    final Picture backgroundPicture = _drawBackground(region);
    builder.addPicture(Offset.zero, backgroundPicture);

    builder.pushClipRect(
      const Rect.fromLTRB(10, 10, 180, 120),
    );
    final Picture circles1 = _drawTestPictureWithCircles(region, 30, 30);

    // current background color is light green, apply a light yellow colorFilter
    const ColorFilter colorFilter = ColorFilter.mode(
      Color(0xFFFFFFB1),
      BlendMode.modulate
    );
    builder.pushBackdropFilter(colorFilter);
    builder.addPicture(Offset.zero, circles1);
    builder.pop();

    domDocument.body!.append(builder
        .build()
        .webOnlyRootElement!);

   await matchGoldenFile('backdrop_filter_colorFilter_as_imageFilter.png',
       region: region);
  });
}

Picture _drawTestPictureWithCircles(Rect region, double offsetX, double offsetY) {
  final EnginePictureRecorder recorder = PictureRecorder() as EnginePictureRecorder;
  final RecordingCanvas canvas =
  recorder.beginRecording(region);
  canvas.drawCircle(
      Offset(offsetX + 10, offsetY + 10), 10, SurfacePaint()..style = PaintingStyle.fill);
  canvas.drawCircle(
      Offset(offsetX + 60, offsetY + 10),
      10,
      SurfacePaint()
        ..style = PaintingStyle.fill
        ..color = const Color.fromRGBO(255, 0, 0, 1));
  canvas.drawCircle(
      Offset(offsetX + 10, offsetY + 60),
      10,
      SurfacePaint()
        ..style = PaintingStyle.fill
        ..color = const Color.fromRGBO(0, 255, 0, 1));
  canvas.drawCircle(
      Offset(offsetX + 60, offsetY + 60),
      10,
      SurfacePaint()
        ..style = PaintingStyle.fill
        ..color = const Color.fromRGBO(0, 0, 255, 1));
  return recorder.endRecording();
}

Picture _drawBackground(Rect region) {
  final EnginePictureRecorder recorder = PictureRecorder() as EnginePictureRecorder;
  final RecordingCanvas canvas =
  recorder.beginRecording(region);
  canvas.drawRect(
      region.deflate(8.0),
      SurfacePaint()
        ..style = PaintingStyle.fill
        ..color = const Color(0xFFE0FFE0)
      );
  return recorder.endRecording();
}
