// 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 'dart:convert';
import 'dart:js_interop';
import 'dart:math';
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 'package:web_engine_tester/golden_tester.dart';

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

const String kGlitchShaderSksl = r'''
{
  "sksl": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform vec2 uResolution;\nuniform float uTime;\nuniform shader uTex;\nuniform half2 uTex_size;\n\nvec4 oColor;\n\nvec2 FLT_flutter_local_FlutterFragCoord()\n{\n    return flutter_FragCoord.xy;\n}\n\nfloat FLT_flutter_local_cubicPulse(float c, float w, inout float x)\n{\n    x = abs(x - c);\n    if (x > w)\n    {\n        return 0.0;\n    }\n    x /= w;\n    return 1.0 - ((x * x) * (3.0 - (2.0 * x)));\n}\n\nfloat FLT_flutter_local_twoSin(inout float x)\n{\n    x = (6.4899997711181640625 * x) - 0.64999997615814208984375;\n    float t = ((-0.699999988079071044921875) * sin(6.80000019073486328125 * x)) + (1.39999997615814208984375 * sin(2.900000095367431640625 * x));\n    t = (t / 4.099999904632568359375) + 0.5;\n    return t;\n}\n\nfloat FLT_flutter_local_hash_1d(float v)\n{\n    float u = 50.0 * sin(v * 3000.0);\n    return (2.0 * fract((2.0 * u) * u)) - 1.0;\n}\n\nvoid FLT_main()\n{\n    vec2 uv = vec2(FLT_flutter_local_FlutterFragCoord()) / uResolution;\n    float param = 0.5;\n    float param_1 = 0.0500000007450580596923828125;\n    float param_2 = fract(uTime / 4.0);\n    float _127 = FLT_flutter_local_cubicPulse(param, param_1, param_2);\n    float t_2 = _127;\n    float param_3 = fract(uTime / 5.0);\n    float _134 = FLT_flutter_local_twoSin(param_3);\n    float t_1 = _134;\n    float glitchScale = mix(0.0, 8.0, t_1 + t_2);\n    float aberrationSize = mix(0.0, 5.0, t_1 + t_2);\n    float param_4 = uv.y;\n    float h = FLT_flutter_local_hash_1d(param_4);\n    float hs = sign(h);\n    h = max(h, 0.0);\n    h *= h;\n    h = floor(h + float(0.5)) * hs;\n    uv += (vec2(h * glitchScale, 0.0) / uResolution);\n    vec2 redOffset = vec2(aberrationSize, 0.0) / uResolution;\n    vec2 greenOffset = vec2(0.0) / uResolution;\n    vec2 blueOffset = vec2(-aberrationSize, 0.0) / uResolution;\n    vec2 redUv = uv + redOffset;\n    vec2 greenUv = uv + greenOffset;\n    vec2 blueUv = uv + blueOffset;\n    vec2 ra = uTex.eval(uTex_size *  redUv).xw;\n    vec2 ga = uTex.eval(uTex_size *  greenUv).yw;\n    vec2 ba = uTex.eval(uTex_size *  blueUv).zw;\n    ra.x /= ra.y;\n    ga.x /= ga.y;\n    ba.x /= ba.y;\n    float alpha = max(ra.y, max(ga.y, ba.y));\n    oColor = vec4(ra.x, ga.x, ba.x, 1.0) * alpha;\n}\n\nhalf4 main(float2 iFragCoord)\n{\n      flutter_FragCoord = float4(iFragCoord, 0, 0);\n      FLT_main();\n      return oColor;\n}\n",
  "stage": 1,
  "target_platform": 2,
  "uniforms": [
    {
      "array_elements": 0,
      "bit_width": 32,
      "columns": 1,
      "location": 0,
      "name": "uResolution",
      "rows": 2,
      "type": 10
    },
    {
      "array_elements": 0,
      "bit_width": 32,
      "columns": 1,
      "location": 1,
      "name": "uTime",
      "rows": 1,
      "type": 10
    },
    {
      "array_elements": 0,
      "bit_width": 0,
      "columns": 1,
      "location": 2,
      "name": "uTex",
      "rows": 1,
      "type": 12
    }
  ]
}
''';

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

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

  late FakeAssetScope assetScope;
  setUp(() {
    assetScope = fakeAssetManager.pushAssetScope();
    assetScope.setAsset(
      'glitch_shader',
      ByteData.sublistView(utf8.encode(kGlitchShaderSksl))
    );
  });

  tearDown(() {
    fakeAssetManager.popAssetScope(assetScope);
  });

  const ui.Rect drawRegion = ui.Rect.fromLTWH(0, 0, 300, 300);
  const ui.Rect imageRegion = ui.Rect.fromLTWH(0, 0, 150, 150);

  // Emits a set of rendering tests for an image
  // `imageGenerator` should produce an image that is 150x150 pixels.
  void emitImageTests(String name, Future<ui.Image> Function() imageGenerator) {
    group(name, () {
      late ui.Image image;
      setUp(() async {
        image = await imageGenerator();
      });

      tearDown(() {
        image.dispose();
      });

      test('drawImage', () async {
        final ui.Image image = await imageGenerator();

        final ui.PictureRecorder recorder = ui.PictureRecorder();
        final ui.Canvas canvas = ui.Canvas(recorder, drawRegion);
        canvas.drawImage(image, const ui.Offset(100, 100), ui.Paint());

        await drawPictureUsingCurrentRenderer(recorder.endRecording());

        await matchGoldenFile('${name}_canvas_drawImage.png', region: drawRegion);
      });

      test('drawImageRect', () async {
        final ui.Image image = await imageGenerator();

        final ui.PictureRecorder recorder = ui.PictureRecorder();
        final ui.Canvas canvas = ui.Canvas(recorder, drawRegion);
        canvas.drawImageRect(
          image,
          const ui.Rect.fromLTRB(50, 50, 100, 100),
          const ui.Rect.fromLTRB(100, 100, 150, 150),
          ui.Paint()
        );

        await drawPictureUsingCurrentRenderer(recorder.endRecording());

        await matchGoldenFile('${name}_canvas_drawImageRect.png', region: drawRegion);
      });

      test('drawImageNine', () async {
        final ui.Image image = await imageGenerator();

        final ui.PictureRecorder recorder = ui.PictureRecorder();
        final ui.Canvas canvas = ui.Canvas(recorder, drawRegion);
        canvas.drawImageNine(
          image,
          const ui.Rect.fromLTRB(50, 50, 100, 100),
          drawRegion,
          ui.Paint()
        );

        await drawPictureUsingCurrentRenderer(recorder.endRecording());

        await matchGoldenFile('${name}_canvas_drawImageNine.png', region: drawRegion);
      });

      test('image_shader_cubic_rotated', () async {
        final ui.Image image = await imageGenerator();

        final Float64List matrix = Matrix4.rotationZ(pi / 6).toFloat64();
        final ui.ImageShader shader = ui.ImageShader(
          image,
          ui.TileMode.repeated,
          ui.TileMode.repeated,
          matrix,
          filterQuality: ui.FilterQuality.high,
        );
        final ui.PictureRecorder recorder = ui.PictureRecorder();
        final ui.Canvas canvas = ui.Canvas(recorder, drawRegion);
        canvas.drawOval(
          const ui.Rect.fromLTRB(0, 50, 300, 250),
          ui.Paint()..shader = shader
        );

        await drawPictureUsingCurrentRenderer(recorder.endRecording());
        await matchGoldenFile('${name}_image_shader_cubic_rotated.png', region: drawRegion);
      });

      test('fragment_shader_sampler', () async {
        final ui.Image image = await imageGenerator();

        final ui.FragmentProgram program = await renderer.createFragmentProgram('glitch_shader');
        final ui.FragmentShader shader = program.fragmentShader();

        // Resolution
        shader.setFloat(0, 300);
        shader.setFloat(1, 300);

        // Time
        shader.setFloat(2, 2);

        // Image
        shader.setImageSampler(0, image);

        final ui.PictureRecorder recorder = ui.PictureRecorder();
        final ui.Canvas canvas = ui.Canvas(recorder, drawRegion);
        canvas.drawCircle(const ui.Offset(150, 150), 100, ui.Paint()..shader = shader);

        await drawPictureUsingCurrentRenderer(recorder.endRecording());

        await matchGoldenFile('${name}_fragment_shader_sampler.png', region: drawRegion);
      }, skip: isHtml); // HTML doesn't support fragment shaders

      test('toByteData_rgba', () async {
        final ui.Image image = await imageGenerator();

        final ByteData? rgbaData = await image.toByteData();
        expect(rgbaData, isNotNull);
        expect(rgbaData!.lengthInBytes, isNonZero);
      });

      test('toByteData_png', () async {
        final ui.Image image = await imageGenerator();

        final ByteData? pngData = await image.toByteData(format: ui.ImageByteFormat.png);
        expect(pngData, isNotNull);
        expect(pngData!.lengthInBytes, isNonZero);
      }, skip: isHtml); // https://github.com/flutter/flutter/issues/126611
    });
  }

  emitImageTests('picture_toImage', () {
    final ui.PictureRecorder recorder = ui.PictureRecorder();
    final ui.Canvas canvas = ui.Canvas(recorder, imageRegion);
    for (int y = 0; y < 15; y++) {
      for (int x = 0; x < 15; x++) {
        final ui.Offset center = ui.Offset(x * 10 + 5, y * 10 + 5);
        final ui.Color color = ui.Color.fromRGBO(
          (center.dx * 256 / 150).round(),
          (center.dy * 256 / 150).round(), 0, 1);
        canvas.drawCircle(center, 5, ui.Paint()..color = color);
      }
    }
    return recorder.endRecording().toImage(150, 150);
  });

  Uint8List generatePixelData(
    int width,
    int height,
    ui.Color Function(double, double) generator
  ) {
    final Uint8List data = Uint8List(width * height * 4);
    int outputIndex = 0;
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        final ui.Color pixelColor = generator(
          (2.0 * x / width) - 1.0,
          (2.0 * y / height) - 1.0,
        );
        data[outputIndex++] = pixelColor.red;
        data[outputIndex++] = pixelColor.green;
        data[outputIndex++] = pixelColor.blue;
        data[outputIndex++] = pixelColor.alpha;
      }
    }
    return data;
  }

  emitImageTests('decodeImageFromPixels_unscaled', () {
    final Uint8List pixels = generatePixelData(150, 150, (double x, double y) {
      final double r = sqrt(x * x + y * y);
      final double theta = atan2(x, y);
      return ui.Color.fromRGBO(
        (255 * (sin(r * 10.0) + 1.0) / 2.0).round(),
        (255 * (sin(theta * 10.0) + 1.0) / 2.0).round(),
        0,
        1,
      );
    });
    final Completer<ui.Image> completer = Completer<ui.Image>();
    ui.decodeImageFromPixels(pixels, 150, 150, ui.PixelFormat.rgba8888, completer.complete);
    return completer.future;
  });

  // https://github.com/flutter/flutter/issues/126603
  if (!isHtml) {
    emitImageTests('decodeImageFromPixels_scaled', () {
      final Uint8List pixels = generatePixelData(50, 50, (double x, double y) {
        final double r = sqrt(x * x + y * y);
        final double theta = atan2(x, y);
        return ui.Color.fromRGBO(
          (255 * (sin(r * 10.0) + 1.0) / 2.0).round(),
          (255 * (sin(theta * 10.0) + 1.0) / 2.0).round(),
          0,
          1,
        );
      });
      final Completer<ui.Image> completer = Completer<ui.Image>();
      ui.decodeImageFromPixels(
        pixels,
        50,
        50,
        ui.PixelFormat.rgba8888,
        completer.complete,
        targetWidth: 150,
        targetHeight: 150,
      );
      return completer.future;
    });
  }

  emitImageTests('codec_uri', () async {
    final ui.Codec codec = await renderer.instantiateImageCodecFromUrl(
      Uri(path: '/test_images/mandrill_128.png')
    );
    expect(codec.frameCount, 1);

    final ui.FrameInfo info = await codec.getNextFrame();
    return info.image;
  });

  // This API doesn't work in headless Firefox due to requiring WebGL
  // See https://github.com/flutter/flutter/issues/109265
  if (!isFirefox) {
    emitImageTests('svg_image_bitmap', () async {
      final DomBlob svgBlob = createDomBlob(<String>[
  '''
  <svg xmlns="http://www.w3.org/2000/svg" width="150" height="150">
    <path d="M25,75  A50,50 0 1,0 125 75 L75,25 Z" stroke="blue" stroke-width="10" fill="red"></path>
  </svg>
  '''
      ], <String, String>{'type': 'image/svg+xml'});
      final String url = domWindow.URL.createObjectURL(svgBlob);
      final DomHTMLImageElement image = createDomHTMLImageElement();
      final Completer<void> completer = Completer<void>();
      late final DomEventListener loadListener;
      loadListener = createDomEventListener((DomEvent event) {
        completer.complete();
        image.removeEventListener('load', loadListener);
      });
      image.addEventListener('load', loadListener);
      image.src = url;
      await completer.future;

      final DomImageBitmap bitmap = await createImageBitmap(image as JSObject);

      expect(bitmap.width.toDartInt, 150);
      expect(bitmap.height.toDartInt, 150);
      final ui.Image uiImage = await renderer.createImageFromImageBitmap(bitmap);

      if (isSkwasm) {
        // Skwasm transfers the bitmap to the web worker, so it should be disposed/consumed.
        expect(bitmap.width.toDartInt, 0);
        expect(bitmap.height.toDartInt, 0);
      }
      return uiImage;
    });
  }

  emitImageTests('codec_list_resized', () async {
    final ByteBuffer data = await httpFetchByteBuffer('/test_images/mandrill_128.png');
    final ui.Codec codec = await renderer.instantiateImageCodec(
      data.asUint8List(),
      targetWidth: 150,
      targetHeight: 150,
    );
    expect(codec.frameCount, 1);

    final ui.FrameInfo info = await codec.getNextFrame();
    return info.image;
  });
}
