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

import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart';

import 'package:web_engine_tester/golden_tester.dart';

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

enum PaintMode {
  kStrokeAndFill,
  kStroke,
  kFill,
  kStrokeWidthOnly,
}

Future<void> testMain() async {
  const Rect region =
      Rect.fromLTWH(8, 8, 600, 400); // Compensate for old scuba tester padding

  Future<void> testPath(Path path, String scubaFileName,
      {SurfacePaint? paint,
      double? maxDiffRatePercent,
      bool write = false,
      PaintMode mode = PaintMode.kStrokeAndFill}) async {
    const Rect canvasBounds = Rect.fromLTWH(0, 0, 600, 400);
    final BitmapCanvas bitmapCanvas =
        BitmapCanvas(canvasBounds, RenderStrategy());
    final RecordingCanvas canvas = RecordingCanvas(canvasBounds);

    final bool enableFill =
        mode == PaintMode.kStrokeAndFill || mode == PaintMode.kFill;
    if (enableFill) {
      paint ??= SurfacePaint()
        ..color = const Color(0x807F7F7F)
        ..style = PaintingStyle.fill;
      canvas.drawPath(path, paint);
    }

    if (mode == PaintMode.kStrokeAndFill || mode == PaintMode.kStroke) {
      paint = SurfacePaint()
        ..strokeWidth = 2
        ..color = enableFill ? const Color(0xFFFF0000) : const Color(0xFF000000)
        ..style = PaintingStyle.stroke;
    }

    if (mode == PaintMode.kStrokeWidthOnly) {
      paint = SurfacePaint()
        ..color = const Color(0xFF4060E0)
        ..strokeWidth = 10;
    }

    canvas.drawPath(path, paint!);

    final html.Element svgElement = pathToSvgElement(path, paint, enableFill);

    html.document.body!.append(bitmapCanvas.rootElement);
    html.document.body!.append(svgElement);

    canvas.endRecording();
    canvas.apply(bitmapCanvas, canvasBounds);

    await matchGoldenFile('$scubaFileName.png',
        region: region, maxDiffRatePercent: maxDiffRatePercent, write: write);

    bitmapCanvas.rootElement.remove();
    svgElement.remove();
  }

  tearDown(() {
    html.document.body!.children.clear();
  });

  test('render line strokes', () async {
    final Path path = Path();
    path.moveTo(50, 60);
    path.lineTo(200, 300);
    await testPath(path, 'svg_stroke_line',
        paint: SurfacePaint()
          ..color = const Color(0xFFFF0000)
          ..strokeWidth = 2.0
          ..style = PaintingStyle.stroke);
  });

  test('render quad bezier curve', () async {
    final Path path = Path();
    path.moveTo(50, 60);
    path.quadraticBezierTo(200, 60, 50, 200);
    await testPath(path, 'svg_quad_bezier');
  });

  test('render cubic curve', () async {
    final Path path = Path();
    path.moveTo(50, 60);
    path.cubicTo(200, 60, -100, -50, 150, 200);
    await testPath(path, 'svg_cubic_bezier');
  });

  test('render arcs', () async {
    final List<ArcSample> arcs = <ArcSample>[
      ArcSample(const Offset(0, 0),
          largeArc: false, clockwise: false, distance: 20),
      ArcSample(const Offset(200, 0),
          largeArc: true, clockwise: false, distance: 20),
      ArcSample(const Offset(0, 0),
          largeArc: false, clockwise: true, distance: 20),
      ArcSample(const Offset(200, 0),
          largeArc: true, clockwise: true, distance: 20),
      ArcSample(const Offset(0, 0),
          largeArc: false, clockwise: false, distance: -20),
      ArcSample(const Offset(200, 0),
          largeArc: true, clockwise: false, distance: -20),
      ArcSample(const Offset(0, 0),
          largeArc: false, clockwise: true, distance: -20),
      ArcSample(const Offset(200, 0),
          largeArc: true, clockwise: true, distance: -20)
    ];
    int sampleIndex = 0;
    for (final ArcSample sample in arcs) {
      ++sampleIndex;
      final Path path = sample.createPath();
      await testPath(path, 'svg_arc_$sampleIndex');
    }
  });

  test('render rect', () async {
    final Path path = Path();
    path.addRect(const Rect.fromLTRB(15, 15, 60, 20));
    path.addRect(const Rect.fromLTRB(35, 160, 15, 100));
    await testPath(path, 'svg_rect', maxDiffRatePercent: 1.0);
  });

  test('render notch', () async {
    final Path path = Path();
    path.moveTo(0, 0);
    path.lineTo(83, 0);
    path.quadraticBezierTo(98, 0, 99.97, 7.8);
    path.arcToPoint(const Offset(162, 7.8),
        radius: const Radius.circular(32),
        largeArc: false,
        clockwise: false,
        rotation: 0);
    path.lineTo(200, 7.8);
    path.lineTo(200, 80);
    path.lineTo(0, 80);
    path.lineTo(0, 10);
    await testPath(path, 'svg_notch');
  });

  /// Regression test for https://github.com/flutter/flutter/issues/70980
  test('render notch', () async {
    const double w = 0.7;
    final Path path = Path();
    path.moveTo(0.5, 14);
    path.conicTo(0.5, 10.5, 4, 10.5, w);
    path.moveTo(4, 10.5);
    path.lineTo(6.5, 10.5);
    path.moveTo(36.0, 10.5);
    path.lineTo(158, 10.5);
    path.conicTo(161.5, 10.5, 161.5, 14, w);
    path.moveTo(161.5, 14);
    path.lineTo(161.5, 48);
    path.conicTo(161.5, 51.5, 158, 51.5, w);
    path.lineTo(4, 51.5);
    path.conicTo(0.5, 51.5, 0.5, 48, w);
    path.lineTo(0.5, 14);
    await testPath(path, 'svg_editoutline', mode: PaintMode.kStroke);
  });

  /// Regression test for https://github.com/flutter/flutter/issues/74416
  test('render stroke', () async {
    final Path path = Path();
    path.moveTo(20, 20);
    path.lineTo(200, 200);
    await testPath(path, 'svg_stroke_width', mode: PaintMode.kStrokeWidthOnly);
  });
}

html.Element pathToSvgElement(Path path, Paint paint, bool enableFill) {
  final Rect bounds = path.getBounds();
  final svg.SvgSvgElement root = svg.SvgSvgElement();
  root.style.transform = 'translate(200px, 0px)';
  root.setAttribute('viewBox', '0 0 ${bounds.right} ${bounds.bottom}');
  root.width!.baseVal!.newValueSpecifiedUnits(svg.Length.SVG_LENGTHTYPE_NUMBER, bounds.right);
  root.height!.baseVal!.newValueSpecifiedUnits(svg.Length.SVG_LENGTHTYPE_NUMBER, bounds.bottom);

  final svg.PathElement pathElement = svg.PathElement();
  root.append(pathElement);
  if (paint.style == PaintingStyle.stroke ||
      paint.strokeWidth != 0.0) {
    pathElement.setAttribute('stroke', colorToCssString(paint.color)!);
    pathElement.setAttribute('stroke-width', paint.strokeWidth);
    if (!enableFill) {
      pathElement.setAttribute('fill', 'none');
    }
  }
  if (paint.style == PaintingStyle.fill) {
    pathElement.setAttribute('fill', colorToCssString(paint.color)!);
  }
  pathElement.setAttribute('d', pathToSvg((path as SurfacePath).pathRef)); // This is what we're testing!
  return root;
}

class ArcSample {
  final Offset offset;
  final bool largeArc;
  final bool clockwise;
  final double distance;

  ArcSample(this.offset,
      {this.largeArc = false, this.clockwise = false, this.distance = 0});

  Path createPath() {
    final Offset startP =
        Offset(75 - distance + offset.dx, 75 - distance + offset.dy);
    final Offset endP =
        Offset(75.0 + distance + offset.dx, 75.0 + distance + offset.dy);
    final Path path = Path();
    path.moveTo(startP.dx, startP.dy);
    path.arcToPoint(endP,
        rotation: 60,
        radius: const Radius.elliptical(40, 60),
        largeArc: largeArc,
        clockwise: clockwise);
    return path;
  }

  // Returns bounds of start/end point of arc.
  Rect getBounds() {
    final Offset startP =
        Offset(75 - distance + offset.dx, 75 - distance + offset.dy);
    final Offset endP =
        Offset(75.0 + distance + offset.dx, 75.0 + distance + offset.dy);
    return Rect.fromLTRB(startP.dx, startP.dy, endP.dx, endP.dy);
  }
}
