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

/// @docImport 'package:fake_async/fake_async.dart';
/// @docImport 'package:flutter/widgets.dart';
///
/// @docImport 'binding.dart';
/// @docImport 'test_compat.dart';
/// @docImport 'widget_tester.dart';
library;

import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/painting.dart';

import 'binding.dart';
import 'test_async_utils.dart';

final Map<int, ui.Image> _cache = <int, ui.Image>{};

/// Creates an arbitrarily sized image for testing.
///
/// If the [cache] parameter is set to true, the image will be cached for the
/// rest of this suite. This is normally desirable, assuming a test suite uses
/// images with the same dimensions in most tests, as it will save on memory
/// usage and CPU time over the course of the suite. However, it should be
/// avoided for images that are used only once in a test suite, especially if
/// the image is large, as it will require holding on to the memory for that
/// image for the duration of the suite.
///
/// This method requires real async work, and will not work properly in the
/// [FakeAsync] zones set up by [testWidgets]. Typically, it should be invoked
/// as a setup step before [testWidgets] are run, such as [setUp] or [setUpAll].
/// If needed, it can be invoked using [WidgetTester.runAsync].
Future<ui.Image> createTestImage({int width = 1, int height = 1, bool cache = true}) =>
    TestAsyncUtils.guard(() async {
      assert(width > 0);
      assert(height > 0);

      final int cacheKey = Object.hash(width, height);
      if (cache && _cache.containsKey(cacheKey)) {
        return _cache[cacheKey]!.clone();
      }

      final ui.Image image = await _createImage(width, height);
      if (cache) {
        _cache[cacheKey] = image.clone();
      }
      return image;
    });

Future<ui.Image> _createImage(int width, int height) async {
  final completer = Completer<ui.Image>();
  ui.decodeImageFromPixels(
    Uint8List.fromList(List<int>.filled(width * height * 4, 0)),
    width,
    height,
    ui.PixelFormat.rgba8888,
    (ui.Image image) {
      completer.complete(image);
    },
  );
  return completer.future;
}

/// Precaches an [ImageProvider] during testing.
///
/// In a widget test, image decoding operations (such as [MemoryImage],
/// [NetworkImage], and [ExactAssetImage]) run asynchronously outside the test's
/// [FakeAsync] zone.
///
/// Calling [precacheTestImage] resolves the image stream in a real async zone
/// (via [TestWidgetsFlutterBinding.runAsync]), loading the decoded image into
/// [imageCache] before the widget tree is pumped.
///
/// Can be called before [WidgetTester.pumpWidget] inside a [testWidgets] body,
/// or inside [setUp] / [setUpAll].
///
/// If [onError] is provided, it will be invoked if an error occurs while
/// precaching. Otherwise, any error will complete the returned future with that error.
Future<void> precacheTestImage(
  ImageProvider provider, {
  ImageConfiguration configuration = ImageConfiguration.empty,
  ImageErrorListener? onError,
}) {
  final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
  Object? caughtError;
  StackTrace? caughtStackTrace;

  Future<void> resolveImage() async {
    final completer = Completer<void>.sync();
    final ImageStream stream = provider.resolve(configuration);
    late final ImageStreamListener listener;
    listener = ImageStreamListener(
      (ImageInfo info, bool syncCall) {
        info.dispose();
        if (!completer.isCompleted) {
          stream.removeListener(listener);
          completer.complete();
        }
      },
      onError: (Object error, StackTrace? stackTrace) {
        if (!completer.isCompleted) {
          stream.removeListener(listener);
          if (onError != null) {
            onError(error, stackTrace);
          } else {
            caughtError = error;
            caughtStackTrace = stackTrace;
          }
          completer.complete();
        }
      },
    );
    stream.addListener(listener);
    await completer.future;
  }

  Future<void> doPrecache() async {
    await binding.runAsync<void>(resolveImage);
    if (caughtError != null) {
      Error.throwWithStackTrace(caughtError!, caughtStackTrace ?? StackTrace.current);
    }
  }

  return TestAsyncUtils.guard(doPrecache);
}
