// 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(
    withImplicitView: true,
    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();
}
