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

/// Utilities for loading images from the network.
///
/// This library expands the capabilities of the basic [Image.network] and
/// [NetworkImage] provided by Flutter core libraries, to include a retry
/// mechanism and connectivity detection.
library network;

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

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

/// Fetches the image from the given URL, associating it with the given scale.
///
/// If [fetchStrategy] is specified, uses it instead of the
/// [defaultFetchStrategy] to obtain instructions for fetching the URL.
///
/// The image will be cached regardless of cache headers from the server.
@immutable
class NetworkImageWithRetry extends ImageProvider<NetworkImageWithRetry> {
  /// Creates an object that fetches the image at the given [url].
  const NetworkImageWithRetry(
    this.url, {
    this.scale = 1.0,
    this.fetchStrategy = defaultFetchStrategy,
    this.headers,
  });

  /// The HTTP client used to download images.
  static final io.HttpClient _client = io.HttpClient();

  /// The URL from which the image will be fetched.
  final String url;

  /// The scale to place in the [ImageInfo] object of the image.
  final double scale;

  /// The strategy used to fetch the [url] and retry when the fetch fails.
  ///
  /// This function is called at least once and may be called multiple times.
  /// The first time it is called, it is passed a null [FetchFailure], which
  /// indicates that this is the first attempt to fetch the [url]. Subsequent
  /// calls pass non-null [FetchFailure] values, which indicate that previous
  /// fetch attempts failed.
  final FetchStrategy fetchStrategy;

  /// HTTP Headers applied to the request.
  ///
  /// Keys from this map will be used as header field names and the
  /// values will be used as header values. A list of header names can
  /// be found at https://datatracker.ietf.org/doc/html/rfc7231#section-8.3
  ///
  /// If the value is a DateTime, an HTTP date format will be applied.
  /// If the value is an Iterable, each element will be added separately.
  /// For all other types the default Object.toString method will be used.
  ///
  /// Header names are converted to lower-case. If two header names are
  /// the same when converted to lower-case, they are considered to be
  /// the same header, with one set of values.
  ///
  /// For example, to add an authorization header to the request:
  ///
  /// final NetworkImageWithRetry subject = NetworkImageWithRetry(
  ///   Uri.parse('https://www.flutter.com/top_secret.png'),
  ///   headers: <String, Object>{
  ///     'Authorization': base64Encode(utf8.encode('user:password'))
  ///   },
  /// );
  final Map<String, Object>? headers;

  /// Used by [defaultFetchStrategy].
  ///
  /// This indirection is necessary because [defaultFetchStrategy] is used as
  /// the default constructor argument value, which requires that it be a const
  /// expression.
  static final FetchStrategy _defaultFetchStrategyFunction =
      const FetchStrategyBuilder().build();

  /// The [FetchStrategy] that [NetworkImageWithRetry] uses by default.
  static Future<FetchInstructions> defaultFetchStrategy(
      Uri uri, FetchFailure? failure) {
    return _defaultFetchStrategyFunction(uri, failure);
  }

  @override
  Future<NetworkImageWithRetry> obtainKey(ImageConfiguration configuration) {
    return SynchronousFuture<NetworkImageWithRetry>(this);
  }

  @override
  ImageStreamCompleter load(NetworkImageWithRetry key, DecoderCallback decode) {
    return OneFrameImageStreamCompleter(_loadWithRetry(key, decode),
        informationCollector: () sync* {
      yield ErrorDescription('Image provider: $this');
      yield ErrorDescription('Image key: $key');
    });
  }

  void _debugCheckInstructions(FetchInstructions? instructions) {
    assert(() {
      if (instructions == null) {
        if (fetchStrategy == defaultFetchStrategy) {
          throw StateError(
              'The default FetchStrategy returned null FetchInstructions. This\n'
              'is likely a bug in $runtimeType. Please file a bug at\n'
              'https://github.com/flutter/flutter/issues.');
        } else {
          throw StateError(
              'The custom FetchStrategy used to fetch $url returned null\n'
              'FetchInstructions. FetchInstructions must never be null, but\n'
              'instead instruct to either make another fetch attempt or give up.');
        }
      }
      return true;
    }());
  }

  Future<ImageInfo> _loadWithRetry(
      NetworkImageWithRetry key, DecoderCallback decode) async {
    assert(key == this);

    final Stopwatch stopwatch = Stopwatch()..start();
    final Uri resolved = Uri.base.resolve(key.url);
    FetchInstructions instructions = await fetchStrategy(resolved, null);
    _debugCheckInstructions(instructions);
    int attemptCount = 0;
    FetchFailure? lastFailure;

    while (!instructions.shouldGiveUp) {
      attemptCount += 1;
      io.HttpClientRequest? request;
      try {
        request = await _client
            .getUrl(instructions.uri)
            .timeout(instructions.timeout);

        headers?.forEach((String key, Object value) {
          request?.headers.add(key, value);
        });

        final io.HttpClientResponse response =
            await request.close().timeout(instructions.timeout);

        if (response.statusCode != 200) {
          throw FetchFailure._(
            totalDuration: stopwatch.elapsed,
            attemptCount: attemptCount,
            httpStatusCode: response.statusCode,
          );
        }

        final _Uint8ListBuilder builder = await response
            .fold(
              _Uint8ListBuilder(),
              (_Uint8ListBuilder buffer, List<int> bytes) => buffer..add(bytes),
            )
            .timeout(instructions.timeout);

        final Uint8List bytes = builder.data;

        if (bytes.lengthInBytes == 0) {
          throw FetchFailure._(
            totalDuration: stopwatch.elapsed,
            attemptCount: attemptCount,
            httpStatusCode: response.statusCode,
          );
        }

        final ui.Codec codec = await decode(bytes);
        final ui.Image image = (await codec.getNextFrame()).image;
        return ImageInfo(
          image: image,
          scale: key.scale,
        );
      } catch (error) {
        request?.close();
        lastFailure = error is FetchFailure
            ? error
            : FetchFailure._(
                totalDuration: stopwatch.elapsed,
                attemptCount: attemptCount,
                originalException: error,
              );
        instructions = await fetchStrategy(instructions.uri, lastFailure);
        _debugCheckInstructions(instructions);
      }
    }

    if (instructions.alternativeImage != null) {
      return instructions.alternativeImage!;
    }

    assert(lastFailure != null);

    if (FlutterError.onError != null) {
      FlutterError.onError!(FlutterErrorDetails(
        exception: lastFailure!,
        library: 'package:flutter_image',
        context:
            ErrorDescription('$runtimeType failed to load ${instructions.uri}'),
      ));
    }

    throw lastFailure!;
  }

  @override
  bool operator ==(dynamic other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    final NetworkImageWithRetry typedOther = other;
    return url == typedOther.url && scale == typedOther.scale;
  }

  @override
  int get hashCode => hashValues(url, scale);

  @override
  String toString() => '$runtimeType("$url", scale: $scale)';
}

/// This function is called to get [FetchInstructions] to fetch an image.
///
/// The instructions are executed as soon as possible after the returned
/// [Future] resolves. If a delay in necessary between retries, use a delayed
/// [Future], such as [Future.delayed]. This is useful for implementing
/// back-off strategies and for recovering from lack of connectivity.
///
/// [uri] is the last requested image URI. A [FetchStrategy] may choose to use
/// a different URI (see [FetchInstructions.uri]).
///
/// If [failure] is `null`, then this is the first attempt to fetch the image.
///
/// If the [failure] is not `null`, it contains the information about the
/// previous attempt to fetch the image. A [FetchStrategy] may attempt to
/// recover from the failure by returning [FetchInstructions] that instruct
/// [NetworkImageWithRetry] to try again.
///
/// See [NetworkImageWithRetry.defaultFetchStrategy] for an example.
typedef FetchStrategy = Future<FetchInstructions> Function(
    Uri uri, FetchFailure? failure);

/// Instructions [NetworkImageWithRetry] uses to fetch the image.
@immutable
class FetchInstructions {
  /// Instructs [NetworkImageWithRetry] to give up trying to download the image.
  const FetchInstructions.giveUp({
    required this.uri,
    this.alternativeImage,
  })  : shouldGiveUp = true,
        timeout = Duration.zero;

  /// Instructs [NetworkImageWithRetry] to attempt to download the image from
  /// the given [uri] and [timeout] if it takes too long.
  const FetchInstructions.attempt({
    required this.uri,
    required this.timeout,
  })  : shouldGiveUp = false,
        alternativeImage = null;

  /// Instructs to give up trying.
  ///
  /// If [alternativeImage] is `null` reports the latest [FetchFailure] to
  /// [FlutterError].
  final bool shouldGiveUp;

  /// Timeout for the next network call.
  final Duration timeout;

  /// The URI to use on the next attempt.
  final Uri uri;

  /// Instructs to give up and use this image instead.
  final Future<ImageInfo>? alternativeImage;

  @override
  String toString() {
    return '$runtimeType(\n'
        '  shouldGiveUp: $shouldGiveUp\n'
        '  timeout: $timeout\n'
        '  uri: $uri\n'
        '  alternativeImage?: ${alternativeImage != null ? 'yes' : 'no'}\n'
        ')';
  }
}

/// Contains information about a failed attempt to fetch an image.
@immutable
class FetchFailure implements Exception {
  const FetchFailure._({
    required this.totalDuration,
    required this.attemptCount,
    this.httpStatusCode,
    this.originalException,
  }) : assert(attemptCount > 0);

  /// The total amount of time it has taken so far to download the image.
  final Duration totalDuration;

  /// The number of times [NetworkImageWithRetry] attempted to fetch the image
  /// so far.
  ///
  /// This value starts with 1 and grows by 1 with each attempt to fetch the
  /// image.
  final int attemptCount;

  /// HTTP status code, such as 500.
  final int? httpStatusCode;

  /// The exception that caused the fetch failure.
  final dynamic originalException;

  @override
  String toString() {
    return '$runtimeType(\n'
        '  attemptCount: $attemptCount\n'
        '  httpStatusCode: $httpStatusCode\n'
        '  totalDuration: $totalDuration\n'
        '  originalException: $originalException\n'
        ')';
  }
}

/// An indefinitely growing builder of a [Uint8List].
class _Uint8ListBuilder {
  static const int _kInitialSize = 100000; // 100KB-ish

  int _usedLength = 0;
  Uint8List _buffer = Uint8List(_kInitialSize);

  Uint8List get data => Uint8List.view(_buffer.buffer, 0, _usedLength);

  void add(List<int> bytes) {
    _ensureCanAdd(bytes.length);
    _buffer.setAll(_usedLength, bytes);
    _usedLength += bytes.length;
  }

  void _ensureCanAdd(int byteCount) {
    final int totalSpaceNeeded = _usedLength + byteCount;

    int newLength = _buffer.length;
    while (totalSpaceNeeded > newLength) {
      newLength *= 2;
    }

    if (newLength != _buffer.length) {
      final Uint8List newBuffer = Uint8List(newLength);
      newBuffer.setAll(0, _buffer);
      newBuffer.setRange(0, _usedLength, _buffer);
      _buffer = newBuffer;
    }
  }
}

/// Determines whether the given HTTP [statusCode] is transient.
typedef TransientHttpStatusCodePredicate = bool Function(int statusCode);

/// Builds a [FetchStrategy] function that retries up to a certain amount of
/// times for up to a certain amount of time.
///
/// Pauses between retries with pauses growing exponentially (known as
/// exponential backoff). Each attempt is subject to a [timeout]. Retries only
/// those HTTP status codes considered transient by a
/// [transientHttpStatusCodePredicate] function.
class FetchStrategyBuilder {
  /// Creates a fetch strategy builder.
  ///
  /// All parameters must be non-null.
  const FetchStrategyBuilder({
    this.timeout = const Duration(seconds: 30),
    this.totalFetchTimeout = const Duration(minutes: 1),
    this.maxAttempts = 5,
    this.initialPauseBetweenRetries = const Duration(seconds: 1),
    this.exponentialBackoffMultiplier = 2,
    this.transientHttpStatusCodePredicate =
        defaultTransientHttpStatusCodePredicate,
  });

  /// A list of HTTP status codes that can generally be retried.
  ///
  /// You may want to use a different list depending on the needs of your
  /// application.
  static const List<int> defaultTransientHttpStatusCodes = <int>[
    0, // Network error
    408, // Request timeout
    500, // Internal server error
    502, // Bad gateway
    503, // Service unavailable
    504 // Gateway timeout
  ];

  /// Maximum amount of time a single fetch attempt is allowed to take.
  final Duration timeout;

  /// A strategy built by this builder will retry for up to this amount of time
  /// before giving up.
  final Duration totalFetchTimeout;

  /// Maximum number of attempts a strategy will make before giving up.
  final int maxAttempts;

  /// Initial amount of time between retries.
  final Duration initialPauseBetweenRetries;

  /// The pause between retries is multiplied by this number with each attempt,
  /// causing it to grow exponentially.
  final num exponentialBackoffMultiplier;

  /// A function that determines whether a given HTTP status code should be
  /// retried.
  final TransientHttpStatusCodePredicate transientHttpStatusCodePredicate;

  /// Uses [defaultTransientHttpStatusCodes] to determine if the [statusCode] is
  /// transient.
  static bool defaultTransientHttpStatusCodePredicate(int statusCode) {
    return defaultTransientHttpStatusCodes.contains(statusCode);
  }

  /// Builds a [FetchStrategy] that operates using the properties of this
  /// builder.
  FetchStrategy build() {
    return (Uri uri, FetchFailure? failure) async {
      if (failure == null) {
        // First attempt. Just load.
        return FetchInstructions.attempt(
          uri: uri,
          timeout: timeout,
        );
      }

      final bool isRetriableFailure = (failure.httpStatusCode != null &&
              transientHttpStatusCodePredicate(failure.httpStatusCode!)) ||
          failure.originalException is io.SocketException;

      // If cannot retry, give up.
      if (!isRetriableFailure || // retrying will not help
          failure.totalDuration > totalFetchTimeout || // taking too long
          failure.attemptCount > maxAttempts) {
        // too many attempts
        return FetchInstructions.giveUp(uri: uri);
      }

      // Exponential back-off.
      final Duration pauseBetweenRetries = initialPauseBetweenRetries *
          math.pow(exponentialBackoffMultiplier, failure.attemptCount - 1);
      await Future<void>.delayed(pauseBetweenRetries);

      // Retry.
      return FetchInstructions.attempt(
        uri: uri,
        timeout: timeout,
      );
    };
  }
}
