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

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';

const MethodCodec codec = StandardMethodCodec();

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

void testMain() {
  group('$HtmlViewEmbedder', () {
    setUpCanvasKitTest();

    setUp(() {
      window.debugOverrideDevicePixelRatio(1);
    });

    test('embeds interactive platform views', () async {
      ui.platformViewRegistry.registerViewFactory(
        'test-platform-view',
        (int viewId) => html.DivElement()..id = 'view-0',
      );
      await _createPlatformView(0, 'test-platform-view');

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;
      final LayerSceneBuilder sb = LayerSceneBuilder();
      sb.pushOffset(0, 0);
      sb.addPlatformView(0, width: 10, height: 10);
      dispatcher.rasterizer!.draw(sb.build().layerTree);

      // The platform view is now split in two parts. The contents live
      // as a child of the glassPane, and the slot lives in the glassPane
      // shadow root. The slot is the one that has pointer events auto.
      final html.Element contents =
          domRenderer.glassPaneElement!.querySelector('#view-0')!;
      final html.Element slot =
          domRenderer.sceneElement!.querySelector('slot')!;
      final html.Element contentsHost = contents.parent!;
      final html.Element slotHost = slot.parent!;

      expect(contents, isNotNull,
          reason: 'The view from the factory is injected in the DOM.');

      expect(contentsHost.tagName, equalsIgnoringCase('flt-platform-view'));
      expect(slotHost.tagName, equalsIgnoringCase('flt-platform-view-slot'));

      expect(slotHost.style.pointerEvents, 'auto',
          reason: 'The slot reenables pointer events.');
      expect(contentsHost.getAttribute('slot'), slot.getAttribute('name'),
          reason: 'The contents and slot are correctly related.');
    });

    test('clips platform views with RRects', () async {
      ui.platformViewRegistry.registerViewFactory(
        'test-platform-view',
        (int viewId) => html.DivElement()..id = 'view-0',
      );
      await _createPlatformView(0, 'test-platform-view');

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;
      final LayerSceneBuilder sb = LayerSceneBuilder();
      sb.pushOffset(0, 0);
      sb.pushClipRRect(
          ui.RRect.fromLTRBR(0, 0, 10, 10, const ui.Radius.circular(3)));
      sb.addPlatformView(0, width: 10, height: 10);
      dispatcher.rasterizer!.draw(sb.build().layerTree);

      expect(
        domRenderer.sceneElement!.querySelectorAll('#sk_path_defs').single,
        isNotNull,
      );
      expect(
        domRenderer.sceneElement!
            .querySelectorAll('#sk_path_defs')
            .single
            .querySelectorAll('clipPath')
            .single,
        isNotNull,
      );
      expect(
        domRenderer.sceneElement!
            .querySelectorAll('flt-clip')
            .single
            .style
            .clipPath,
        'url("#svgClip1")',
      );
    });

    test('correctly transforms platform views', () async {
      ui.platformViewRegistry.registerViewFactory(
        'test-platform-view',
        (int viewId) => html.DivElement()..id = 'view-0',
      );
      await _createPlatformView(0, 'test-platform-view');

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;
      final LayerSceneBuilder sb = LayerSceneBuilder();
      sb.pushOffset(0, 0);
      final Matrix4 scaleMatrix = Matrix4.identity()
        ..scale(5, 5)
        ..translate(100, 100);
      sb.pushTransform(scaleMatrix.toFloat64());
      sb.pushOffset(3, 3);
      sb.addPlatformView(0, width: 10, height: 10);
      dispatcher.rasterizer!.draw(sb.build().layerTree);

      // Transformations happen on the slot element.
      final html.Element slotHost =
          domRenderer.sceneElement!.querySelector('flt-platform-view-slot')!;

      expect(
        slotHost.style.transform,
        // We should apply the scale matrix first, then the offset matrix.
        // So the translate should be 515 (5 * 100 + 5 * 3), and not
        // 503 (5 * 100 + 3).
        'matrix3d(5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 515, 515, 0, 1)',
      );
    });

    // Returns the list of CSS transforms applied to the ancestor chain of
    // elements starting from `viewHost`, up until and excluding <flt-scene>.
    List<String> getTransformChain(html.Element viewHost) {
      final List<String> chain = <String>[];
      html.Element? element = viewHost;
      while (element != null && element.tagName.toLowerCase() != 'flt-scene') {
        chain.add(element.style.transform);
        element = element.parent;
      }
      return chain;
    }

    test('converts device pixels to logical pixels (no clips)', () async {
      window.debugOverrideDevicePixelRatio(4);
      ui.platformViewRegistry.registerViewFactory(
        'test-platform-view',
        (int viewId) => html.DivElement()..id = 'view-0',
      );
      await _createPlatformView(0, 'test-platform-view');

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;
      final LayerSceneBuilder sb = LayerSceneBuilder();
      sb.pushOffset(1, 1);
      sb.pushOffset(2, 2);
      sb.pushOffset(3, 3);
      sb.addPlatformView(0, width: 10, height: 10);
      dispatcher.rasterizer!.draw(sb.build().layerTree);

      // Transformations happen on the slot element.
      final html.Element slotHost =
          domRenderer.sceneElement!.querySelector('flt-platform-view-slot')!;

      expect(
        getTransformChain(slotHost),
        <String>['matrix(0.25, 0, 0, 0.25, 1.5, 1.5)'],
      );
    });

    test('converts device pixels to logical pixels (with clips)', () async {
      window.debugOverrideDevicePixelRatio(4);
      ui.platformViewRegistry.registerViewFactory(
        'test-platform-view',
        (int viewId) => html.DivElement()..id = 'view-0',
      );
      await _createPlatformView(0, 'test-platform-view');

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;
      final LayerSceneBuilder sb = LayerSceneBuilder();
      sb.pushOffset(3, 3);
      sb.pushClipRect(ui.Rect.largest);
      sb.pushOffset(6, 6);
      sb.pushClipRect(ui.Rect.largest);
      sb.pushOffset(9, 9);
      sb.addPlatformView(0, width: 10, height: 10);
      dispatcher.rasterizer!.draw(sb.build().layerTree);

      // Transformations happen on the slot element.
      final html.Element slotHost =
          domRenderer.sceneElement!.querySelector('flt-platform-view-slot')!;

      expect(
        getTransformChain(slotHost),
        <String>[
          'matrix(1, 0, 0, 1, 9, 9)',
          'matrix(1, 0, 0, 1, 6, 6)',
          'matrix(0.25, 0, 0, 0.25, 0.75, 0.75)',
        ],
      );
    });

    test('renders overlays on top of platform views', () async {
      expect(SurfaceFactory.instance.debugCacheSize, 0);
      final CkPicture testPicture =
          paintPicture(const ui.Rect.fromLTRB(0, 0, 10, 10), (CkCanvas canvas) {
        canvas.drawCircle(const ui.Offset(5, 5), 5, CkPaint());
      });

      // Initialize all platform views to be used in the test.
      final List<int> platformViewIds = <int>[];
      for (int i = 0; i < configuration.canvasKitMaximumSurfaces * 2; i++) {
        ui.platformViewRegistry.registerViewFactory(
          'test-platform-view',
          (int viewId) => html.DivElement()..id = 'view-$i',
        );
        await _createPlatformView(i, 'test-platform-view');
        platformViewIds.add(i);
      }

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;

      void renderTestScene({required int viewCount}) {
        final LayerSceneBuilder sb = LayerSceneBuilder();
        sb.pushOffset(0, 0);
        for (int i = 0; i < viewCount; i++) {
          sb.addPicture(ui.Offset.zero, testPicture);
          sb.addPlatformView(i, width: 10, height: 10);
        }
        dispatcher.rasterizer!.draw(sb.build().layerTree);
      }

      int countCanvases() {
        return domRenderer.sceneElement!.querySelectorAll('canvas').length;
      }

      // Frame 1:
      //   Render: up to cache size platform views.
      //   Expect: main canvas plus platform view overlays.
      renderTestScene(viewCount: configuration.canvasKitMaximumSurfaces);
      expect(countCanvases(), configuration.canvasKitMaximumSurfaces);

      // Frame 2:
      //   Render: zero platform views.
      //   Expect: main canvas, no overlays.
      await Future<void>.delayed(Duration.zero);
      renderTestScene(viewCount: 0);
      expect(countCanvases(), 1);

      // Frame 3:
      //   Render: less than cache size platform views.
      //   Expect: overlays reused.
      await Future<void>.delayed(Duration.zero);
      renderTestScene(viewCount: configuration.canvasKitMaximumSurfaces - 2);
      expect(countCanvases(), configuration.canvasKitMaximumSurfaces - 1);

      // Frame 4:
      //   Render: more platform views than max cache size.
      //   Expect: main canvas, backup overlay, maximum overlays.
      await Future<void>.delayed(Duration.zero);
      renderTestScene(viewCount: configuration.canvasKitMaximumSurfaces * 2);
      expect(countCanvases(), configuration.canvasKitMaximumSurfaces);

      // Frame 5:
      //   Render: zero platform views.
      //   Expect: main canvas, no overlays.
      await Future<void>.delayed(Duration.zero);
      renderTestScene(viewCount: 0);
      expect(countCanvases(), 1);

      // Frame 6:
      //   Render: deleted platform views.
      //   Expect: error.
      for (final int id in platformViewIds) {
        const StandardMethodCodec codec = StandardMethodCodec();
        final Completer<void> completer = Completer<void>();
        ui.window.sendPlatformMessage(
          'flutter/platform_views',
          codec.encodeMethodCall(MethodCall(
            'dispose',
            id,
          )),
          completer.complete,
        );
        await completer.future;
      }

      try {
        renderTestScene(viewCount: platformViewIds.length);
        fail('Expected to throw');
      } on AssertionError catch (error) {
        expect(
          error.toString(),
          'Assertion failed: "Cannot render platform views: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15. These views have not been created, or they have been deleted."',
        );
      }

      // Frame 7:
      //   Render: a platform view after error.
      //   Expect: success. Just checking the system is not left in a corrupted state.
      await _createPlatformView(0, 'test-platform-view');
      renderTestScene(viewCount: 0);
      // TODO(yjbanov): skipped due to https://github.com/flutter/flutter/issues/73867
    }, skip: isSafari);

    test('correctly reuses overlays', () async {
      final CkPicture testPicture =
          paintPicture(const ui.Rect.fromLTRB(0, 0, 10, 10), (CkCanvas canvas) {
        canvas.drawCircle(const ui.Offset(5, 5), 5, CkPaint());
      });

      // Initialize all platform views to be used in the test.
      final List<int> platformViewIds = <int>[];
      for (int i = 0; i < 20; i++) {
        ui.platformViewRegistry.registerViewFactory(
          'test-platform-view',
          (int viewId) => html.DivElement()..id = 'view-$i',
        );
        await _createPlatformView(i, 'test-platform-view');
        platformViewIds.add(i);
      }

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;

      void renderTestScene(List<int> views) {
        final LayerSceneBuilder sb = LayerSceneBuilder();
        sb.pushOffset(0, 0);
        for (final int view in views) {
          sb.addPicture(ui.Offset.zero, testPicture);
          sb.addPlatformView(view, width: 10, height: 10);
        }
        dispatcher.rasterizer!.draw(sb.build().layerTree);
      }

      int countCanvases() {
        return domRenderer.sceneElement!.querySelectorAll('canvas').length;
      }

      // Frame 1:
      //   Render: Views 1-10
      //   Expect: main canvas plus platform view overlays; empty cache.
      renderTestScene(<int>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
      expect(countCanvases(), configuration.canvasKitMaximumSurfaces);

      // Frame 2:
      //   Render: Views 2-11
      //   Expect: main canvas plus platform view overlays; empty cache.
      await Future<void>.delayed(Duration.zero);
      renderTestScene(<int>[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
      expect(countCanvases(), configuration.canvasKitMaximumSurfaces);

      // Frame 3:
      //   Render: Views 3-12
      //   Expect: main canvas plus platform view overlays; empty cache.
      await Future<void>.delayed(Duration.zero);
      renderTestScene(<int>[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
      expect(countCanvases(), configuration.canvasKitMaximumSurfaces);

      // TODO(yjbanov): skipped due to https://github.com/flutter/flutter/issues/73867
    }, skip: isSafari);

    test('embeds and disposes of a platform view', () async {
      ui.platformViewRegistry.registerViewFactory(
        'test-platform-view',
        (int viewId) => html.DivElement()..id = 'view-0',
      );
      await _createPlatformView(0, 'test-platform-view');

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;

      LayerSceneBuilder sb = LayerSceneBuilder();
      sb.pushOffset(0, 0);
      sb.addPlatformView(0, width: 10, height: 10);
      dispatcher.rasterizer!.draw(sb.build().layerTree);

      expect(
        domRenderer.sceneElement!.querySelector('flt-platform-view-slot'),
        isNotNull,
      );
      expect(
        domRenderer.glassPaneElement!.querySelector('flt-platform-view'),
        isNotNull,
      );

      await _disposePlatformView(0);

      sb = LayerSceneBuilder();
      sb.pushOffset(0, 0);
      dispatcher.rasterizer!.draw(sb.build().layerTree);

      expect(
        domRenderer.sceneElement!.querySelector('flt-platform-view-slot'),
        isNull,
      );
      expect(
        domRenderer.glassPaneElement!.querySelector('flt-platform-view'),
        isNull,
      );
    });

    test('removed the DOM node of an unrendered platform view', () async {
      ui.platformViewRegistry.registerViewFactory(
        'test-platform-view',
        (int viewId) => html.DivElement()..id = 'view-0',
      );
      await _createPlatformView(0, 'test-platform-view');

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;

      LayerSceneBuilder sb = LayerSceneBuilder();
      sb.pushOffset(0, 0);
      sb.addPlatformView(0, width: 10, height: 10);
      dispatcher.rasterizer!.draw(sb.build().layerTree);

      expect(
        domRenderer.sceneElement!.querySelector('flt-platform-view-slot'),
        isNotNull,
      );
      expect(
        domRenderer.glassPaneElement!.querySelector('flt-platform-view'),
        isNotNull,
      );

      // Render a frame with a different platform view.
      await _createPlatformView(1, 'test-platform-view');
      sb = LayerSceneBuilder();
      sb.pushOffset(0, 0);
      sb.addPlatformView(1, width: 10, height: 10);
      dispatcher.rasterizer!.draw(sb.build().layerTree);

      expect(
          domRenderer.sceneElement!.querySelectorAll('flt-platform-view-slot'),
          hasLength(1));
      expect(
          domRenderer.glassPaneElement!.querySelectorAll('flt-platform-view'),
          hasLength(2));

      // Render a frame without a platform view, but also without disposing of
      // the platform view.
      sb = LayerSceneBuilder();
      sb.pushOffset(0, 0);
      dispatcher.rasterizer!.draw(sb.build().layerTree);

      expect(
        domRenderer.sceneElement!.querySelector('flt-platform-view-slot'),
        isNull,
      );
      // The actual contents of the platform view are kept in the dom, until
      // it's actually disposed of!
      expect(
        domRenderer.glassPaneElement!.querySelector('flt-platform-view'),
        isNotNull,
      );
    });

    test(
        'removes old SVG clip definitions from the DOM when the view is recomposited',
        () async {
      ui.platformViewRegistry.registerViewFactory(
        'test-platform-view',
        (int viewId) => html.DivElement()..id = 'test-view',
      );
      await _createPlatformView(0, 'test-platform-view');

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;

      void renderTestScene() {
        final LayerSceneBuilder sb = LayerSceneBuilder();
        sb.pushOffset(0, 0);
        sb.pushClipRRect(
            ui.RRect.fromLTRBR(0, 0, 10, 10, const ui.Radius.circular(3)));
        sb.addPlatformView(0, width: 10, height: 10);
        dispatcher.rasterizer!.draw(sb.build().layerTree);
      }

      final html.Node skPathDefs =
          domRenderer.sceneElement!.querySelector('#sk_path_defs')!;

      expect(skPathDefs.childNodes, hasLength(0));

      renderTestScene();
      expect(skPathDefs.childNodes, hasLength(1));

      await Future<void>.delayed(Duration.zero);
      renderTestScene();
      expect(skPathDefs.childNodes, hasLength(1));

      await Future<void>.delayed(Duration.zero);
      renderTestScene();
      expect(skPathDefs.childNodes, hasLength(1));
    });

    test('diffViewList works in the expected case', () {
      ViewListDiffResult? result = diffViewList(
        <int>[1, 2, 3, 4, 5],
        <int>[3, 4, 5, 6, 7],
      );
      expect(result, isNotNull);
      expect(result!.viewsToAdd, <int>[6, 7]);
      expect(result.viewsToRemove, <int>[1, 2]);
      expect(result.addToBeginning, isFalse);

      result = diffViewList(
        <int>[3, 4, 5, 6, 7],
        <int>[1, 2, 3, 4, 5],
      );
      expect(result, isNotNull);
      expect(result!.viewsToAdd, <int>[1, 2]);
      expect(result.viewsToRemove, <int>[6, 7]);
      expect(result.addToBeginning, isTrue);
      expect(result.viewToInsertBefore, 3);

      result = diffViewList(<int>[3, 4, 5], <int>[2, 3, 4, 5]);
      expect(result, isNotNull);
      expect(result!.viewsToAdd, <int>[2]);
      expect(result.viewsToRemove, <int>[]);
      expect(result.addToBeginning, isTrue);
      expect(result.viewToInsertBefore, 3);

      result = diffViewList(<int>[3, 4, 5], <int>[3, 4, 5, 6]);
      expect(result, isNotNull);
      expect(result!.viewsToAdd, <int>[6]);
      expect(result.viewsToRemove, <int>[]);
      expect(result.addToBeginning, isFalse);

      result = diffViewList(<int>[3, 4, 5, 6], <int>[3, 4, 5]);
      expect(result, isNotNull);
      expect(result!.viewsToAdd, <int>[]);
      expect(result.viewsToRemove, <int>[6]);
      expect(result.addToBeginning, isTrue);
      expect(result.viewToInsertBefore, 3);

      result = diffViewList(<int>[3, 4, 5, 6], <int>[4, 5, 6]);
      expect(result, isNotNull);
      expect(result!.viewsToAdd, <int>[]);
      expect(result.viewsToRemove, <int>[3]);
      expect(result.addToBeginning, isFalse);

      result = diffViewList(<int>[1, 2, 3], <int>[4, 5]);
      expect(result, isNull);

      result = diffViewList(<int>[1, 2, 3, 4], <int>[2, 3, 5, 4]);
      expect(result, isNull);

      result = diffViewList(<int>[3, 4], <int>[1, 2, 3, 4, 5, 6]);
      expect(result, isNull);
    });

    test('does not crash when a prerolled platform view is not composited',
        () async {
      ui.platformViewRegistry.registerViewFactory(
        'test-platform-view',
        (int viewId) => html.DivElement()..id = 'view-0',
      );
      await _createPlatformView(0, 'test-platform-view');

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;

      final LayerSceneBuilder sb = LayerSceneBuilder();
      sb.pushOffset(0, 0);
      sb.pushClipRect(ui.Rect.zero);
      sb.addPlatformView(0, width: 10, height: 10);
      sb.pop();
      // The below line should not throw an error.
      dispatcher.rasterizer!.draw(sb.build().layerTree);
      expect(
          domRenderer.glassPaneShadow!
              .querySelectorAll('flt-platform-view-slot'),
          isEmpty);
    });

    test('does not crash when overlays are disabled', () async {
      HtmlViewEmbedder.debugDisableOverlays = true;
      ui.platformViewRegistry.registerViewFactory(
        'test-platform-view',
        (int viewId) => html.DivElement()..id = 'view-0',
      );
      await _createPlatformView(0, 'test-platform-view');

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;

      final LayerSceneBuilder sb = LayerSceneBuilder();
      sb.pushOffset(0, 0);
      sb.addPlatformView(0, width: 10, height: 10);
      sb.pop();
      // The below line should not throw an error.
      dispatcher.rasterizer!.draw(sb.build().layerTree);
      expect(
          domRenderer.glassPaneShadow!
              .querySelectorAll('flt-platform-view-slot'),
          hasLength(1));
      HtmlViewEmbedder.debugDisableOverlays = false;
    });

    test(
        'correctly renders when overlays are disabled and a subset '
        'of views is used', () async {
      HtmlViewEmbedder.debugDisableOverlays = true;
      ui.platformViewRegistry.registerViewFactory(
        'test-platform-view',
        (int viewId) => html.DivElement()..id = 'view-0',
      );
      await _createPlatformView(0, 'test-platform-view');
      await _createPlatformView(1, 'test-platform-view');

      final EnginePlatformDispatcher dispatcher =
          ui.window.platformDispatcher as EnginePlatformDispatcher;

      LayerSceneBuilder sb = LayerSceneBuilder();
      sb.pushOffset(0, 0);
      sb.addPlatformView(0, width: 10, height: 10);
      sb.addPlatformView(1, width: 10, height: 10);
      sb.pop();
      // The below line should not throw an error.
      dispatcher.rasterizer!.draw(sb.build().layerTree);

      expect(
          domRenderer.glassPaneShadow!
              .querySelectorAll('flt-platform-view-slot'),
          hasLength(2));

      sb = LayerSceneBuilder();
      sb.pushOffset(0, 0);
      sb.addPlatformView(1, width: 10, height: 10);
      sb.pop();
      // The below line should not throw an error.
      dispatcher.rasterizer!.draw(sb.build().layerTree);
      expect(
          domRenderer.glassPaneShadow!
              .querySelectorAll('flt-platform-view-slot'),
          hasLength(1));

      HtmlViewEmbedder.debugDisableOverlays = false;
    });
    // TODO(dit): https://github.com/flutter/flutter/issues/60040
  }, skip: isIosSafari);
}

// Sends a platform message to create a Platform View with the given id and viewType.
Future<void> _createPlatformView(int id, String viewType) {
  final Completer<void> completer = Completer<void>();
  window.sendPlatformMessage(
    'flutter/platform_views',
    codec.encodeMethodCall(MethodCall(
      'create',
      <String, dynamic>{
        'id': id,
        'viewType': viewType,
      },
    )),
    (dynamic _) => completer.complete(),
  );
  return completer.future;
}

Future<void> _disposePlatformView(int id) {
  final Completer<void> completer = Completer<void>();
  window.sendPlatformMessage(
    'flutter/platform_views',
    codec.encodeMethodCall(MethodCall('dispose', id)),
    (dynamic _) => completer.complete(),
  );
  return completer.future;
}
