// Copyright 2014 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:typed_data';
import 'dart:ui' as ui;

import 'recorder.dart';

// Measures the performance of image decoding.
//
// The benchmark measures the decoding latency and not impact on jank. It
// cannot distinguish between blocking and non-blocking decoding. It naively
// measures the total time it takes to decode image frames. For example, the
// WASM codecs execute on the main thread and block the UI, leading to jank,
// but the browser's WebCodecs API is asynchronous running on a separate thread
// and does not jank. However, the benchmark result may be the same.
//
// This benchmark does not support the HTML renderer because the HTML renderer
// cannot decode image frames (it always returns 1 dummy frame, even for
// animated images).
class BenchImageDecoding extends RawRecorder {
  BenchImageDecoding() : super(
    name: benchmarkName,
    useCustomWarmUp: true,
  );

  static const String benchmarkName = 'bench_image_decoding';

  // These test images are taken from https://github.com/flutter/flutter_gallery_assets/tree/master/lib/splash_effects
  static const List<String> _imageUrls = <String>[
    'assets/packages/flutter_gallery_assets/splash_effects/splash_effect_1.gif',
    'assets/packages/flutter_gallery_assets/splash_effects/splash_effect_2.gif',
    'assets/packages/flutter_gallery_assets/splash_effects/splash_effect_3.gif',
  ];

  final List<Uint8List> _imageData = <Uint8List>[];

  @override
  Future<void> setUpAll() async {
    if (_imageData.isNotEmpty) {
      return;
    }
    for (final String imageUrl in _imageUrls) {
      final html.Body image = await html.window.fetch(imageUrl) as html.Body;
      _imageData.add((await image.arrayBuffer() as ByteBuffer).asUint8List());
    }
  }

  // The number of samples recorded so far.
  int _sampleCount = 0;

  // The number of samples used for warm-up.
  static const int _warmUpSampleCount = 5;

  // The number of samples used to measure performance after the warm-up.
  static const int _measuredSampleCount = 20;

  @override
  Future<void> body(Profile profile) async {
    await profile.recordAsync('recordImageDecode', () async {
      final List<Future<void>> allDecodes = <Future<void>>[
        for (final Uint8List data in _imageData)
          _decodeImage(data),
      ];
      await Future.wait(allDecodes);
    }, reported: true);

    _sampleCount += 1;
    if (_sampleCount == _warmUpSampleCount) {
      profile.stopWarmingUp();
    }
    if (_sampleCount >= _warmUpSampleCount + _measuredSampleCount) {
      profile.stopBenchmark();
    }
  }
}

Future<void> _decodeImage(Uint8List data) async {
  final ui.Codec codec = await ui.instantiateImageCodec(data);
  const int decodeFrameCount = 5;
  if (codec.frameCount < decodeFrameCount) {
    throw Exception(
      'Test image contains too few frames for this benchmark (${codec.frameCount}). '
      'Choose a test image with at least $decodeFrameCount frames.'
    );
  }
  for (int i = 0; i < decodeFrameCount; i++) {
    (await codec.getNextFrame()).image.dispose();
  }
  codec.dispose();
}
