// 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:async';
import 'dart:io' show HttpOverrides;

import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';
import 'package:flutter_image/network.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:quiver/testing/async.dart';

String _imageUrl(String fileName) {
  return 'http://localhost:11111/$fileName';
}

void main() {
  AutomatedTestWidgetsFlutterBinding();
  HttpOverrides.global = null;

  group('NetworkImageWithRetry', () {
    group('succeeds', () {
      setUp(() {
        FlutterError.onError = (FlutterErrorDetails error) {
          fail('$error');
        };
      });

      tearDown(() {
        FlutterError.onError = FlutterError.dumpErrorToConsole;
      });

      test('loads image from network', () async {
        final NetworkImageWithRetry subject = NetworkImageWithRetry(
          _imageUrl('immediate_success.png'),
        );

        assertThatImageLoadingSucceeds(subject);
      });

      test('loads image from network with an extra header', () async {
        final NetworkImageWithRetry subject = NetworkImageWithRetry(
          _imageUrl('extra_header.png'),
          headers: const <String, Object>{'ExtraHeader': 'special'},
        );

        assertThatImageLoadingSucceeds(subject);
      });

      test('succeeds on successful retry', () async {
        final NetworkImageWithRetry subject = NetworkImageWithRetry(
          _imageUrl('error.png'),
          fetchStrategy: (Uri uri, FetchFailure? failure) async {
            if (failure == null) {
              return FetchInstructions.attempt(
                uri: uri,
                timeout: const Duration(minutes: 1),
              );
            } else {
              expect(failure.attemptCount, lessThan(2));
              return FetchInstructions.attempt(
                uri: Uri.parse(_imageUrl('immediate_success.png')),
                timeout: const Duration(minutes: 1),
              );
            }
          },
        );
        assertThatImageLoadingSucceeds(subject);
      });
    });

    group('fails', () {
      final List<FlutterErrorDetails> errorLog = <FlutterErrorDetails>[];
      FakeAsync fakeAsync = FakeAsync();

      setUp(() {
        FlutterError.onError = errorLog.add;
      });

      tearDown(() {
        fakeAsync = FakeAsync();
        errorLog.clear();
        FlutterError.onError = FlutterError.dumpErrorToConsole;
      });

      test('retries 6 times then gives up', () async {
        final VoidCallback maxAttemptCountReached = expectAsync0(() {});

        int attemptCount = 0;
        Future<void> onAttempt() async {
          expect(attemptCount, lessThan(7));
          if (attemptCount == 6) {
            maxAttemptCountReached();
          }
          await Future<void>.delayed(Duration.zero);
          fakeAsync.elapse(const Duration(seconds: 60));
          attemptCount++;
        }

        final NetworkImageWithRetry subject = NetworkImageWithRetry(
          _imageUrl('error.png'),
          fetchStrategy: (Uri uri, FetchFailure? failure) {
            Timer.run(onAttempt);
            return fakeAsync.run((FakeAsync fakeAsync) {
              return NetworkImageWithRetry.defaultFetchStrategy(uri, failure);
            }) as Future<FetchInstructions>;
          },
        );

        assertThatImageLoadingFails(subject, errorLog);
      });

      test('gives up immediately on non-retriable errors (HTTP 404)', () async {
        int attemptCount = 0;
        Future<void> onAttempt() async {
          expect(attemptCount, lessThan(2));
          await Future<void>.delayed(Duration.zero);
          fakeAsync.elapse(const Duration(seconds: 60));
          attemptCount++;
        }

        final NetworkImageWithRetry subject = NetworkImageWithRetry(
          _imageUrl('does_not_exist.png'),
          fetchStrategy: (Uri uri, FetchFailure? failure) {
            Timer.run(onAttempt);
            return fakeAsync.run((FakeAsync fakeAsync) {
              return NetworkImageWithRetry.defaultFetchStrategy(uri, failure);
            }) as Future<FetchInstructions>;
          },
        );

        assertThatImageLoadingFails(subject, errorLog);
      });
    });
  });
}

void assertThatImageLoadingFails(
  NetworkImageWithRetry subject,
  List<FlutterErrorDetails> errorLog,
) {
  final ImageStreamCompleter completer = subject.load(
    subject,
    // TODO(cyanglaz): migrate to use the new APIs
    // https://github.com/flutter/flutter/issues/105336
    // ignore: deprecated_member_use
    PaintingBinding.instance.instantiateImageCodec,
  );
  completer.addListener(ImageStreamListener(
    (ImageInfo image, bool synchronousCall) {},
    onError: expectAsync2((Object error, StackTrace? _) {
      expect(errorLog.single.exception, isInstanceOf<FetchFailure>());
      expect(error, isInstanceOf<FetchFailure>());
      expect(error, equals(errorLog.single.exception));
    }),
  ));
}

void assertThatImageLoadingSucceeds(
  NetworkImageWithRetry subject,
) {
  final ImageStreamCompleter completer = subject.load(
    subject,
    // TODO(cyanglaz): migrate to use the new APIs
    // https://github.com/flutter/flutter/issues/105336
    // ignore: deprecated_member_use
    PaintingBinding.instance.instantiateImageCodec,
  );
  completer.addListener(ImageStreamListener(
    expectAsync2((ImageInfo image, bool synchronousCall) {
      expect(image.image.height, 1);
      expect(image.image.width, 1);
    }),
  ));
}
