// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. 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:math' as math;

import 'package:async/async.dart';
import 'package:http/http.dart';

/// An HTTP client wrapper that automatically retries failing requests.
class RetryClient extends BaseClient {
  /// The wrapped client.
  final Client _inner;

  /// The number of times a request should be retried.
  final int _retries;

  /// The callback that determines whether a request should be retried.
  final bool Function(BaseResponse) _when;

  /// The callback that determines how long to wait before retrying a request.
  final Duration Function(int) _delay;

  /// The callback to call to indicate that a request is being retried.
  final void Function(BaseRequest, BaseResponse, int) _onRetry;

  /// Creates a client wrapping [inner] that retries HTTP requests.
  ///
  /// This retries a failing request [retries] times (3 by default). Note that
  /// `n` retries means that the request will be sent at most `n + 1` times.
  ///
  /// By default, this retries requests whose responses have status code 503
  /// Temporary Failure. If [when] is passed, it retries any request for whose
  /// response [when] returns `true`.
  ///
  /// By default, this waits 500ms between the original request and the first
  /// retry, then increases the delay by 1.5x for each subsequent retry. If
  /// [delay] is passed, it's used to determine the time to wait before the
  /// given (zero-based) retry.
  ///
  /// If [onRetry] is passed, it's called immediately before each retry so that
  /// the client has a chance to perform side effects like logging.
  RetryClient(this._inner,
      {int retries,
      bool when(BaseResponse response),
      Duration delay(int retryCount),
      void onRetry(BaseRequest request, BaseResponse response, int retryCount)})
      : _retries = retries ?? 3,
        _when = when ?? ((response) => response.statusCode == 503),
        _delay = delay ??
            ((retryCount) =>
                new Duration(milliseconds: 500) * math.pow(1.5, retryCount)),
        _onRetry = onRetry {
    RangeError.checkNotNegative(_retries, "retries");
  }

  /// Like [new RetryClient], but with a pre-computed list of [delays]
  /// between each retry.
  ///
  /// This will retry a request at most `delays.length` times, using each delay
  /// in order. It will wait for `delays[0]` after the initial request,
  /// `delays[1]` after the first retry, and so on.
  RetryClient.withDelays(Client inner, Iterable<Duration> delays,
      {bool when(BaseResponse response),
      void onRetry(BaseRequest request, BaseResponse response, int retryCount)})
      : this._withDelays(inner, delays.toList(), when: when, onRetry: onRetry);

  RetryClient._withDelays(Client inner, List<Duration> delays,
      {bool when(BaseResponse response),
      void onRetry(BaseRequest request, BaseResponse response, int retryCount)})
      : this(inner,
            retries: delays.length,
            delay: (retryCount) => delays[retryCount],
            when: when,
            onRetry: onRetry);

  Future<StreamedResponse> send(BaseRequest request) async {
    var splitter = new StreamSplitter(request.finalize());

    var i = 0;
    while (true) {
      var response = await _inner.send(_copyRequest(request, splitter.split()));
      if (i == _retries || !_when(response)) return response;

      // Make sure the response stream is listened to so that we don't leave
      // dangling connections.
      response.stream.listen((_) {}).cancel()?.catchError((_) {});
      await new Future.delayed(_delay(i));
      if (_onRetry != null) _onRetry(request, response, i);
      i++;
    }
  }

  /// Returns a copy of [original] with the given [body].
  StreamedRequest _copyRequest(BaseRequest original, Stream<List<int>> body) {
    var request = new StreamedRequest(original.method, original.url);
    request.contentLength = original.contentLength;
    request.followRedirects = original.followRedirects;
    request.headers.addAll(original.headers);
    request.maxRedirects = original.maxRedirects;
    request.persistentConnection = original.persistentConnection;

    body.listen(request.sink.add,
        onError: request.sink.addError,
        onDone: request.sink.close,
        cancelOnError: true);

    return request;
  }

  void close() => _inner.close();
}
