// 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:typed_data';
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;

import 'common.dart';

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

void testMain() {
  List<CkColorFilter> createColorFilters() {
     return <CkColorFilter>[
       createCkColorFilter(const EngineColorFilter.mode(ui.Color(0x12345678), ui.BlendMode.srcOver))!,
       createCkColorFilter(const EngineColorFilter.mode(ui.Color(0x12345678), ui.BlendMode.dstOver))!,
       createCkColorFilter(const EngineColorFilter.mode(ui.Color(0x87654321), ui.BlendMode.dstOver))!,
       createCkColorFilter(const EngineColorFilter.matrix(<double>[
          1, 0, 0, 0, 0,
          0, 1, 0, 0, 0,
          0, 0, 1, 0, 0,
          0, 0, 0, 1, 0,
       ]))!,
       createCkColorFilter(EngineColorFilter.matrix(Float32List.fromList(<double>[
          2, 0, 0, 0, 0,
          0, 2, 0, 0, 0,
          0, 0, 2, 0, 0,
          0, 0, 0, 2, 0,
       ])))!,
       createCkColorFilter(const EngineColorFilter.linearToSrgbGamma())!,
       createCkColorFilter(const EngineColorFilter.srgbToLinearGamma())!,
    ];
  }

  List<CkImageFilter> createImageFilters() {
    return <CkImageFilter>[
      CkImageFilter.blur(sigmaX: 5, sigmaY: 6, tileMode: ui.TileMode.clamp),
      CkImageFilter.blur(sigmaX: 6, sigmaY: 5, tileMode: ui.TileMode.clamp),
      CkImageFilter.blur(sigmaX: 6, sigmaY: 5, tileMode: ui.TileMode.decal),
      for (final CkColorFilter colorFilter in createColorFilters()) CkImageFilter.color(colorFilter: colorFilter),
    ];
  }

  setUpCanvasKitTest();

  group('ImageFilters', () {
    test('can be constructed', () {
      final CkImageFilter imageFilter = CkImageFilter.blur(sigmaX: 5, sigmaY: 10, tileMode: ui.TileMode.clamp);
      expect(imageFilter, isA<CkImageFilter>());
      expect(imageFilter.createDefault(), isNotNull);
      expect(imageFilter.resurrect(), isNotNull);
    });


    test('== operator', () {
      final List<ui.ImageFilter> filters1 = <ui.ImageFilter>[
        ...createImageFilters(),
        ...createColorFilters(),
      ];
      final List<ui.ImageFilter> filters2 = <ui.ImageFilter>[
        ...createImageFilters(),
        ...createColorFilters(),
      ];

      for (int index1 = 0; index1 < filters1.length; index1 += 1) {
        final ui.ImageFilter imageFilter1 = filters1[index1];
        expect(imageFilter1 == imageFilter1, isTrue);
        for (int index2 = 0; index2 < filters2.length; index2 += 1) {
          final ui.ImageFilter imageFilter2 = filters2[index2];
          expect(imageFilter1 == imageFilter2, imageFilter2 == imageFilter1);
          expect(imageFilter1 == imageFilter2, index1 == index2);
        }
      }
    });

    test('reuses the Skia filter', () {
      final CkPaint paint = CkPaint();
      paint.imageFilter = CkImageFilter.blur(sigmaX: 5, sigmaY: 10, tileMode: ui.TileMode.clamp);

      final ManagedSkiaObject<Object> managedFilter = paint.imageFilter! as ManagedSkiaObject<Object>;
      final Object skiaFilter = managedFilter.skiaObject;

      paint.imageFilter = CkImageFilter.blur(sigmaX: 5, sigmaY: 10, tileMode: ui.TileMode.clamp);
      expect((paint.imageFilter! as ManagedSkiaObject<Object>).skiaObject, same(skiaFilter));
    });

    test('does not throw for both sigmaX and sigmaY set to 0', () async {
      final CkImageFilter imageFilter = CkImageFilter.blur(sigmaX: 0, sigmaY: 0, tileMode: ui.TileMode.clamp);
      expect(imageFilter, isNotNull);

      const ui.Rect region = ui.Rect.fromLTRB(0, 0, 500, 250);

      final LayerSceneBuilder builder = LayerSceneBuilder();
      builder.pushOffset(0,0);
      final CkPictureRecorder recorder = CkPictureRecorder();
      final CkCanvas canvas = recorder.beginRecording(region);

      canvas.drawCircle(
        const ui.Offset(75, 125),
        50,
        CkPaint()..color = const ui.Color.fromARGB(255, 255, 0, 0),
      );
      final CkPicture redCircle1 = recorder.endRecording();
      builder.addPicture(ui.Offset.zero, redCircle1);

      builder.pushImageFilter(imageFilter);

      // Draw another red circle and apply it to the scene.
      // This one should also be red with the image filter doing nothing
      final CkPictureRecorder recorder2 = CkPictureRecorder();
      final CkCanvas canvas2 = recorder2.beginRecording(region);
      canvas2.drawCircle(
        const ui.Offset(425, 125),
        50,
        CkPaint()..color = const ui.Color.fromARGB(255, 255, 0, 0),
      );
      final CkPicture redCircle2 = recorder2.endRecording();

      builder.addPicture(ui.Offset.zero, redCircle2);

      await matchSceneGolden('canvaskit_zero_sigma_blur.png', builder.build(), region: region);
    });

    test('using a colorFilter', () async {
      final CkColorFilter colorFilter = createCkColorFilter(
        const EngineColorFilter.mode(
          ui.Color.fromARGB(255, 0, 255, 0),
          ui.BlendMode.srcIn
          ))!;

      const ui.Rect region = ui.Rect.fromLTRB(0, 0, 500, 250);

      final LayerSceneBuilder builder = LayerSceneBuilder();
      builder.pushOffset(0,0);

      builder.pushImageFilter(colorFilter);

      final CkPictureRecorder recorder = CkPictureRecorder();
      final CkCanvas canvas = recorder.beginRecording(region);

      canvas.drawCircle(
        const ui.Offset(75, 125),
        50,
        CkPaint()..color = const ui.Color.fromARGB(255, 255, 0, 0),
      );
      final CkPicture redCircle1 = recorder.endRecording();
      builder.addPicture(ui.Offset.zero, redCircle1);
      // The drawn red circle should actually be green with the colorFilter.

      await matchSceneGolden('canvaskit_imageFilter_using_colorFilter.png', builder.build(), region: region);
    });
  });

  group('MaskFilter', () {
    test('with 0 sigma can be set on a Paint', () {
      final ui.Paint paint = ui.Paint();
      const ui.MaskFilter filter = ui.MaskFilter.blur(ui.BlurStyle.normal, 0);

      expect(() => paint.maskFilter = filter, isNot(throwsException));
    });

  });
}
