// 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: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;

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

Future<void> testMain() async {
  await ui.webOnlyInitializePlatform();
  runCanvasTests(deviceClipRoundsOut: false);
}

void runCanvasTests({required bool deviceClipRoundsOut}) {
  setUp(() {
    EngineSemanticsOwner.debugResetSemantics();
  });

  group('ui.Canvas transform tests', () {
    void transformsClose(Float64List value, Float64List expected) {
      expect(expected.length, equals(16));
      expect(value.length, equals(16));
      for (int r = 0; r < 4; r++) {
        for (int c = 0; c < 4; c++) {
          expect(value[r*4 + c], closeTo(expected[r*4 + c], 1e-10));
        }
      }
    }

    void transformsNotClose(Float64List value, Float64List expected) {
      // We check the lengths here even though [transformsClose] will
      // check them so that the [TestFailure] we catch below can only
      // be due to a difference in matrix values.
      expect(expected.length, equals(16));
      expect(value.length, equals(16));
      try {
        transformsClose(value, expected);
      } on TestFailure {
        return;
      }
      throw TestFailure('transforms were too close to equal'); // ignore: only_throw_errors
    }

    test('ui.Canvas.translate affects canvas.getTransform', () {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(recorder);
      canvas.translate(12, 14.5);
      final Float64List matrix = Matrix4.translationValues(12, 14.5, 0).toFloat64();
      final Float64List curMatrix = canvas.getTransform();
      transformsClose(curMatrix, matrix);
      canvas.translate(10, 10);
      final Float64List newCurMatrix = canvas.getTransform();
      transformsNotClose(newCurMatrix, matrix);
      transformsClose(curMatrix, matrix);
    });

    test('ui.Canvas.scale affects canvas.getTransform', () {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(recorder);
      canvas.scale(12, 14.5);
      final Float64List matrix = Matrix4.diagonal3Values(12, 14.5, 1).toFloat64();
      final Float64List curMatrix = canvas.getTransform();
      transformsClose(curMatrix, matrix);
      canvas.scale(10, 10);
      final Float64List newCurMatrix = canvas.getTransform();
      transformsNotClose(newCurMatrix, matrix);
      transformsClose(curMatrix, matrix);
    });

    test('Canvas.rotate affects canvas.getTransform', () async {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(recorder);
      canvas.rotate(pi);
      final Float64List matrix = Matrix4.rotationZ(pi).toFloat64();
      final Float64List curMatrix = canvas.getTransform();
      transformsClose(curMatrix, matrix);
      canvas.rotate(pi / 2);
      final Float64List newCurMatrix = canvas.getTransform();
      transformsNotClose(newCurMatrix, matrix);
      transformsClose(curMatrix, matrix);
    });

    test('Canvas.skew affects canvas.getTransform', () async {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(recorder);
      canvas.skew(12, 14.5);
      final Float64List matrix = (Matrix4.identity()..setEntry(0, 1, 12)..setEntry(1, 0, 14.5)).toFloat64();
      final Float64List curMatrix = canvas.getTransform();
      transformsClose(curMatrix, matrix);
      canvas.skew(10, 10);
      final Float64List newCurMatrix = canvas.getTransform();
      transformsNotClose(newCurMatrix, matrix);
      transformsClose(curMatrix, matrix);
    });

    test('Canvas.transform affects canvas.getTransform', () async {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(recorder);
      final Float64List matrix = (Matrix4.identity()..translate(12.0, 14.5)..scale(12.0, 14.5)).toFloat64();
      canvas.transform(matrix);
      final Float64List curMatrix = canvas.getTransform();
      transformsClose(curMatrix, matrix);
      canvas.translate(10, 10);
      final Float64List newCurMatrix = canvas.getTransform();
      transformsNotClose(newCurMatrix, matrix);
      transformsClose(curMatrix, matrix);
    });
  });

  void rectsClose(ui.Rect value, ui.Rect expected) {
    expect(value.left,   closeTo(expected.left,   1e-6));
    expect(value.top,    closeTo(expected.top,    1e-6));
    expect(value.right,  closeTo(expected.right,  1e-6));
    expect(value.bottom, closeTo(expected.bottom, 1e-6));
  }

  void rectsNotClose(ui.Rect value, ui.Rect expected) {
    try {
      rectsClose(value, expected);
    } on TestFailure {
      return;
    }
    throw TestFailure('transforms were too close to equal'); // ignore: only_throw_errors
  }

  group('ui.Canvas clip tests', () {
    test('Canvas.clipRect affects canvas.getClipBounds', () async {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(recorder, const ui.Rect.fromLTRB(0, 0, 100, 100));
      const ui.Rect clipRawBounds = ui.Rect.fromLTRB(10.2, 11.3, 20.4, 25.7);
      const ui.Rect clipExpandedBounds = ui.Rect.fromLTRB(10, 11, 21, 26);
      final ui.Rect clipDestBounds = deviceClipRoundsOut ? clipExpandedBounds : clipRawBounds;
      canvas.clipRect(clipRawBounds);

      // Save initial return values for testing restored values
      final ui.Rect initialLocalBounds = canvas.getLocalClipBounds();
      final ui.Rect initialDestinationBounds = canvas.getDestinationClipBounds();
      rectsClose(initialLocalBounds, clipExpandedBounds);
      rectsClose(initialDestinationBounds, clipDestBounds);

      canvas.save();
      canvas.clipRect(const ui.Rect.fromLTRB(0, 0, 15, 15));
      // Both clip bounds have changed
      rectsNotClose(canvas.getLocalClipBounds(), clipExpandedBounds);
      rectsNotClose(canvas.getDestinationClipBounds(), clipDestBounds);
      // Previous return values have not changed
      rectsClose(initialLocalBounds, clipExpandedBounds);
      rectsClose(initialDestinationBounds, clipDestBounds);
      canvas.restore();

      // save/restore returned the values to their original values
      expect(canvas.getLocalClipBounds(), initialLocalBounds);
      expect(canvas.getDestinationClipBounds(), initialDestinationBounds);

      canvas.save();
      canvas.scale(2, 2);
      const ui.Rect scaledExpandedBounds = ui.Rect.fromLTRB(5, 5.5, 10.5, 13);
      rectsClose(canvas.getLocalClipBounds(), scaledExpandedBounds);
      // Destination bounds are unaffected by transform
      rectsClose(canvas.getDestinationClipBounds(), clipDestBounds);
      canvas.restore();

      // save/restore returned the values to their original values
      expect(canvas.getLocalClipBounds(), initialLocalBounds);
      expect(canvas.getDestinationClipBounds(), initialDestinationBounds);
    });

    test('Canvas.clipRRect affects canvas.getClipBounds', () async {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(recorder, const ui.Rect.fromLTRB(0, 0, 100, 100));
      const ui.Rect clipRawBounds = ui.Rect.fromLTRB(10.2, 11.3, 20.4, 25.7);
      const ui.Rect clipExpandedBounds = ui.Rect.fromLTRB(10, 11, 21, 26);
      final ui.Rect clipDestBounds = deviceClipRoundsOut ? clipExpandedBounds : clipRawBounds;
      final ui.RRect clip = ui.RRect.fromRectAndRadius(clipRawBounds, const ui.Radius.circular(3));
      canvas.clipRRect(clip);

      // Save initial return values for testing restored values
      final ui.Rect initialLocalBounds = canvas.getLocalClipBounds();
      final ui.Rect initialDestinationBounds = canvas.getDestinationClipBounds();
      rectsClose(initialLocalBounds, clipExpandedBounds);
      rectsClose(initialDestinationBounds, clipDestBounds);

      canvas.save();
      canvas.clipRect(const ui.Rect.fromLTRB(0, 0, 15, 15));
      // Both clip bounds have changed
      rectsNotClose(canvas.getLocalClipBounds(), clipExpandedBounds);
      rectsNotClose(canvas.getDestinationClipBounds(), clipDestBounds);
      // Previous return values have not changed
      rectsClose(initialLocalBounds, clipExpandedBounds);
      rectsClose(initialDestinationBounds, clipDestBounds);
      canvas.restore();

      // save/restore returned the values to their original values
      expect(canvas.getLocalClipBounds(), initialLocalBounds);
      expect(canvas.getDestinationClipBounds(), initialDestinationBounds);

      canvas.save();
      canvas.scale(2, 2);
      const ui.Rect scaledExpandedBounds = ui.Rect.fromLTRB(5, 5.5, 10.5, 13);
      rectsClose(canvas.getLocalClipBounds(), scaledExpandedBounds);
      // Destination bounds are unaffected by transform
      rectsClose(canvas.getDestinationClipBounds(), clipDestBounds);
      canvas.restore();

      // save/restore returned the values to their original values
      expect(canvas.getLocalClipBounds(), initialLocalBounds);
      expect(canvas.getDestinationClipBounds(), initialDestinationBounds);
    });

    test('Canvas.clipPath affects canvas.getClipBounds', () async {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(recorder, const ui.Rect.fromLTRB(0, 0, 100, 100));
      const ui.Rect clipRawBounds = ui.Rect.fromLTRB(10.2, 11.3, 20.4, 25.7);
      const ui.Rect clipExpandedBounds = ui.Rect.fromLTRB(10, 11, 21, 26);
      final ui.Rect clipDestBounds = deviceClipRoundsOut ? clipExpandedBounds : clipRawBounds;
      final ui.Path clip = ui.Path()..addRect(clipRawBounds)..addOval(clipRawBounds);
      canvas.clipPath(clip);

      // Save initial return values for testing restored values
      final ui.Rect initialLocalBounds = canvas.getLocalClipBounds();
      final ui.Rect initialDestinationBounds = canvas.getDestinationClipBounds();
      rectsClose(initialLocalBounds, clipExpandedBounds);
      rectsClose(initialDestinationBounds, clipDestBounds);

      canvas.save();
      canvas.clipRect(const ui.Rect.fromLTRB(0, 0, 15, 15));
      // Both clip bounds have changed
      rectsNotClose(canvas.getLocalClipBounds(), clipExpandedBounds);
      rectsNotClose(canvas.getDestinationClipBounds(), clipDestBounds);
      // Previous return values have not changed
      rectsClose(initialLocalBounds, clipExpandedBounds);
      rectsClose(initialDestinationBounds, clipDestBounds);
      canvas.restore();

      // save/restore returned the values to their original values
      expect(canvas.getLocalClipBounds(), initialLocalBounds);
      expect(canvas.getDestinationClipBounds(), initialDestinationBounds);

      canvas.save();
      canvas.scale(2, 2);
      const ui.Rect scaledExpandedBounds = ui.Rect.fromLTRB(5, 5.5, 10.5, 13);
      rectsClose(canvas.getLocalClipBounds(), scaledExpandedBounds);
      // Destination bounds are unaffected by transform
      rectsClose(canvas.getDestinationClipBounds(), clipDestBounds);
      canvas.restore();

      // save/restore returned the values to their original values
      expect(canvas.getLocalClipBounds(), initialLocalBounds);
      expect(canvas.getDestinationClipBounds(), initialDestinationBounds);
    });

    test('Canvas.clipRect(diff) does not affect canvas.getClipBounds', () async {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(recorder, const ui.Rect.fromLTRB(0, 0, 100, 100));
      const ui.Rect clipRawBounds = ui.Rect.fromLTRB(10.2, 11.3, 20.4, 25.7);
      const ui.Rect clipExpandedBounds = ui.Rect.fromLTRB(10, 11, 21, 26);
      final ui.Rect clipDestBounds = deviceClipRoundsOut ? clipExpandedBounds : clipRawBounds;
      canvas.clipRect(clipRawBounds);

      // Save initial return values for testing restored values
      final ui.Rect initialLocalBounds = canvas.getLocalClipBounds();
      final ui.Rect initialDestinationBounds = canvas.getDestinationClipBounds();
      rectsClose(initialLocalBounds, clipExpandedBounds);
      rectsClose(initialDestinationBounds, clipDestBounds);

      canvas.clipRect(const ui.Rect.fromLTRB(0, 0, 15, 15), clipOp: ui.ClipOp.difference);
      expect(canvas.getLocalClipBounds(), initialLocalBounds);
      expect(canvas.getDestinationClipBounds(), initialDestinationBounds);
    });
  });

  group('RestoreToCount function tests', () {
    test('RestoreToCount can work', () async {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(recorder);
      canvas.save();
      canvas.save();
      canvas.save();
      canvas.save();
      canvas.save();
      expect(canvas.getSaveCount(), 6);
      canvas.restoreToCount(2);
      expect(canvas.getSaveCount(), 2);
      canvas.restore();
      expect(canvas.getSaveCount(), 1);
    });

    test('RestoreToCount count less than 1, the stack should be reset', () async {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(recorder);
      canvas.save();
      canvas.save();
      canvas.save();
      canvas.save();
      canvas.save();
      expect(canvas.getSaveCount(), equals(6));
      canvas.restoreToCount(0);
      expect(canvas.getSaveCount(), equals(1));
    });

    test('RestoreToCount count greater than current [getSaveCount]', () async {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(recorder);
      canvas.save();
      canvas.save();
      canvas.save();
      canvas.save();
      canvas.save();
      expect(canvas.getSaveCount(), equals(6));
      canvas.restoreToCount(canvas.getSaveCount() + 1);
      expect(canvas.getSaveCount(), equals(6));
    });
  });
}
