// 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.

// @dart = 2.6

import 'package:mockito/mockito.dart';
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';

import 'package:ui/ui.dart' as ui;
import 'package:ui/src/engine.dart';

import 'common.dart';
import '../matchers.dart';

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

void testMain() {
  group('skia_objects_cache', () {
    _tests();
    // TODO: https://github.com/flutter/flutter/issues/60040
  }, skip: isIosSafari);
}

void _tests() {
  SkiaObjects.maximumCacheSize = 4;
  bool originalBrowserSupportsFinalizationRegistry;

  setUpAll(() async {
    await ui.webOnlyInitializePlatform();

    // Pretend the browser does not support FinalizationRegistry so we can test the
    // resurrection logic.
    originalBrowserSupportsFinalizationRegistry = browserSupportsFinalizationRegistry;
    browserSupportsFinalizationRegistry = false;
  });

  tearDownAll(() {
    browserSupportsFinalizationRegistry = originalBrowserSupportsFinalizationRegistry;
  });

  group(ManagedSkiaObject, () {
    test('implements create, cache, delete, resurrect, delete lifecycle', () {
      int addPostFrameCallbackCount = 0;

      MockRasterizer mockRasterizer = MockRasterizer();
      when(mockRasterizer.addPostFrameCallback(any)).thenAnswer((_) {
        addPostFrameCallbackCount++;
      });
      window.rasterizer = mockRasterizer;

      // Trigger first create
      final TestSkiaObject testObject = TestSkiaObject();
      expect(SkiaObjects.resurrectableObjects.single, testObject);
      expect(testObject.createDefaultCount, 1);
      expect(testObject.resurrectCount, 0);
      expect(testObject.deleteCount, 0);

      // Check that the getter does not have side-effects
      final SkPaint skiaObject1 = testObject.skiaObject;
      expect(skiaObject1, isNotNull);
      expect(SkiaObjects.resurrectableObjects.single, testObject);
      expect(testObject.createDefaultCount, 1);
      expect(testObject.resurrectCount, 0);
      expect(testObject.deleteCount, 0);

      // Trigger first delete
      SkiaObjects.postFrameCleanUp();
      expect(SkiaObjects.resurrectableObjects, isEmpty);
      expect(addPostFrameCallbackCount, 1);
      expect(testObject.createDefaultCount, 1);
      expect(testObject.resurrectCount, 0);
      expect(testObject.deleteCount, 1);

      // Trigger resurrect
      final SkPaint skiaObject2 = testObject.skiaObject;
      expect(skiaObject2, isNotNull);
      expect(skiaObject2, isNot(same(skiaObject1)));
      expect(SkiaObjects.resurrectableObjects.single, testObject);
      expect(addPostFrameCallbackCount, 1);
      expect(testObject.createDefaultCount, 1);
      expect(testObject.resurrectCount, 1);
      expect(testObject.deleteCount, 1);

      // Trigger final delete
      SkiaObjects.postFrameCleanUp();
      expect(SkiaObjects.resurrectableObjects, isEmpty);
      expect(addPostFrameCallbackCount, 1);
      expect(testObject.createDefaultCount, 1);
      expect(testObject.resurrectCount, 1);
      expect(testObject.deleteCount, 2);
    });

    test('is added to SkiaObjects cache if expensive', () {
      TestSkiaObject object1 = TestSkiaObject(isExpensive: true);
      expect(SkiaObjects.expensiveCache.length, 1);
      expect(SkiaObjects.expensiveCache.debugContains(object1), isTrue);

      TestSkiaObject object2 = TestSkiaObject(isExpensive: true);
      expect(SkiaObjects.expensiveCache.length, 2);
      expect(SkiaObjects.expensiveCache.debugContains(object2), isTrue);

      SkiaObjects.postFrameCleanUp();
      expect(SkiaObjects.expensiveCache.length, 2);
      expect(SkiaObjects.expensiveCache.debugContains(object1), isTrue);
      expect(SkiaObjects.expensiveCache.debugContains(object2), isTrue);

      /// Add 3 more objects to the cache to overflow it.
      TestSkiaObject(isExpensive: true);
      TestSkiaObject(isExpensive: true);
      TestSkiaObject(isExpensive: true);
      expect(SkiaObjects.expensiveCache.length, 5);
      expect(SkiaObjects.cachesToResize.length, 1);

      SkiaObjects.postFrameCleanUp();
      expect(object1.deleteCount, 1);
      expect(object2.deleteCount, 1);
      expect(SkiaObjects.expensiveCache.length, 3);
      expect(SkiaObjects.expensiveCache.debugContains(object1), isFalse);
      expect(SkiaObjects.expensiveCache.debugContains(object2), isFalse);
    });
  });

  group(OneShotSkiaObject, () {
    test('is added to SkiaObjects cache', () {
      TestOneShotSkiaObject.deleteCount = 0;
      OneShotSkiaObject object1 = TestOneShotSkiaObject();
      expect(SkiaObjects.oneShotCache.length, 1);
      expect(SkiaObjects.oneShotCache.debugContains(object1), isTrue);

      OneShotSkiaObject object2 = TestOneShotSkiaObject();
      expect(SkiaObjects.oneShotCache.length, 2);
      expect(SkiaObjects.oneShotCache.debugContains(object2), isTrue);

      SkiaObjects.postFrameCleanUp();
      expect(SkiaObjects.oneShotCache.length, 2);
      expect(SkiaObjects.oneShotCache.debugContains(object1), isTrue);
      expect(SkiaObjects.oneShotCache.debugContains(object2), isTrue);

      // Add 3 more objects to the cache to overflow it.
      TestOneShotSkiaObject();
      TestOneShotSkiaObject();
      TestOneShotSkiaObject();
      expect(SkiaObjects.oneShotCache.length, 5);
      expect(SkiaObjects.cachesToResize.length, 1);

      SkiaObjects.postFrameCleanUp();
      expect(TestOneShotSkiaObject.deleteCount, 2);
      expect(SkiaObjects.oneShotCache.length, 3);
      expect(SkiaObjects.oneShotCache.debugContains(object1), isFalse);
      expect(SkiaObjects.oneShotCache.debugContains(object2), isFalse);
    });
  });


  group(SkiaObjectBox, () {
    test('Records stack traces and respects refcounts', () async {
      TestOneShotSkiaObject.deleteCount = 0;
      final TestOneShotSkiaObject skObject = TestOneShotSkiaObject();
      final Object wrapper = Object();
      final SkiaObjectBox box = SkiaObjectBox(wrapper, skObject);

      expect(box.debugGetStackTraces().length, 1);

      final SkiaObjectBox clone = box.clone(wrapper);
      expect(clone, isNot(same(box)));
      expect(clone.debugGetStackTraces().length, 2);
      expect(box.debugGetStackTraces().length, 2);

      box.delete();

      expect(() => box.clone(wrapper), throwsAssertionError);

      expect(box.isDeleted, true);

      // Let any timers elapse.
      await Future<void>.delayed(Duration.zero);
      expect(TestOneShotSkiaObject.deleteCount, 0);

      expect(clone.debugGetStackTraces().length, 1);
      expect(box.debugGetStackTraces().length, 1);

      clone.delete();
      expect(() => clone.clone(wrapper), throwsAssertionError);

      // Let any timers elapse.
      await Future<void>.delayed(Duration.zero);
      expect(TestOneShotSkiaObject.deleteCount, 1);

      expect(clone.debugGetStackTraces().length, 0);
      expect(box.debugGetStackTraces().length, 0);
    });
  });
}

class TestOneShotSkiaObject extends OneShotSkiaObject<SkPaint> implements SkDeletable {
  static int deleteCount = 0;

  TestOneShotSkiaObject() : super(SkPaint());

  @override
  void delete() {
    rawSkiaObject?.delete();
    deleteCount++;
  }
}

class TestSkiaObject extends ManagedSkiaObject<SkPaint> {
  int createDefaultCount = 0;
  int resurrectCount = 0;
  int deleteCount = 0;

  final bool isExpensive;

  TestSkiaObject({this.isExpensive = false});

  @override
  SkPaint createDefault() {
    createDefaultCount++;
    return SkPaint();
  }

  @override
  SkPaint resurrect() {
    resurrectCount++;
    return SkPaint();
  }

  @override
  void delete() {
    rawSkiaObject?.delete();
    deleteCount++;
  }

  @override
  bool get isResurrectionExpensive => isExpensive;
}

class MockRasterizer extends Mock implements Rasterizer {}
