text: // Copyright (c) Microsoft Corporation.
  // Licensed under the MIT license.
  import { __awaiter, __extends, __generator } from "tslib";
  import * as utils from "../util/utils";
  import { BaseRequestPolicy } from "./requestPolicy";
  import { DEFAULT_CLIENT_MAX_RETRY_INTERVAL, DEFAULT_CLIENT_RETRY_COUNT, DEFAULT_CLIENT_RETRY_INTERVAL, isNumber, updateRetryData, shouldRetry } from "../util/exponentialBackoffStrategy";
  import { RestError } from "../restError";
  import { logger } from "../log";
  export function exponentialRetryPolicy(retryCount, retryInterval, maxRetryInterval) {
      return {
          create: function (nextPolicy, options) {
              return new ExponentialRetryPolicy(nextPolicy, options, retryCount, retryInterval, maxRetryInterval);
          }
      };
  }
  /**
   * Describes the Retry Mode type. Currently supporting only Exponential.
   * @enum RetryMode
   */
  export var RetryMode;
  (function (RetryMode) {
      RetryMode[RetryMode["Exponential"] = 0] = "Exponential";
  })(RetryMode || (RetryMode = {}));
  export var DefaultRetryOptions = {
      maxRetries: DEFAULT_CLIENT_RETRY_COUNT,
      retryDelayInMs: DEFAULT_CLIENT_RETRY_INTERVAL,
      maxRetryDelayInMs: DEFAULT_CLIENT_MAX_RETRY_INTERVAL
  };
  /**
   * @class
   * Instantiates a new "ExponentialRetryPolicyFilter" instance.
   */
  var ExponentialRetryPolicy = /** @class */ (function (_super) {
      __extends(ExponentialRetryPolicy, _super);
      /**
       * @constructor
       * @param {RequestPolicy} nextPolicy The next RequestPolicy in the pipeline chain.
       * @param {RequestPolicyOptions} options The options for this RequestPolicy.
       * @param {number} [retryCount]        The client retry count.
       * @param {number} [retryInterval]     The client retry interval, in milliseconds.
       * @param {number} [minRetryInterval]  The minimum retry interval, in milliseconds.
       * @param {number} [maxRetryInterval]  The maximum retry interval, in milliseconds.
       */
      function ExponentialRetryPolicy(nextPolicy, options, retryCount, retryInterval, maxRetryInterval) {
          var _this = _super.call(this, nextPolicy, options) || this;
          _this.retryCount = isNumber(retryCount) ? retryCount : DEFAULT_CLIENT_RETRY_COUNT;
          _this.retryInterval = isNumber(retryInterval) ? retryInterval : DEFAULT_CLIENT_RETRY_INTERVAL;
          _this.maxRetryInterval = isNumber(maxRetryInterval)
              ? maxRetryInterval
              : DEFAULT_CLIENT_MAX_RETRY_INTERVAL;
          return _this;
      }
      ExponentialRetryPolicy.prototype.sendRequest = function (request) {
          var _this = this;
          return this._nextPolicy
              .sendRequest(request.clone())
              .then(function (response) { return retry(_this, request, response); })
              .catch(function (error) { return retry(_this, request, error.response, undefined, error); });
      };
      return ExponentialRetryPolicy;
  }(BaseRequestPolicy));
  export { ExponentialRetryPolicy };
  function retry(policy, request, response, retryData, requestError) {
      return __awaiter(this, void 0, void 0, function () {
          function shouldPolicyRetry(response) {
              var statusCode = response === null || response === void 0 ? void 0 : response.status;
              if (statusCode === undefined ||
                  (statusCode < 500 && statusCode !== 408) ||
                  statusCode === 501 ||
                  statusCode === 505) {
                  return false;
              }
              return true;
          }
          var isAborted, res, err_1, err;
          return __generator(this, function (_a) {
              switch (_a.label) {
                  case 0:
                      retryData = updateRetryData({
                          retryInterval: policy.retryInterval,
                          minRetryInterval: 0,
                          maxRetryInterval: policy.maxRetryInterval
                      }, retryData, requestError);
                      isAborted = request.abortSignal && request.abortSignal.aborted;
                      if (!(!isAborted && shouldRetry(policy.retryCount, shouldPolicyRetry, retryData, response))) return [3 /*break*/, 6];
                      logger.info("Retrying request in " + retryData.retryInterval);
                      _a.label = 1;
                  case 1:
                      _a.trys.push([1, 4, , 5]);
                      return [4 /*yield*/, utils.delay(retryData.retryInterval)];
                  case 2:
                      _a.sent();
                      return [4 /*yield*/, policy._nextPolicy.sendRequest(request.clone())];
                  case 3:
                      res = _a.sent();
                      return [2 /*return*/, retry(policy, request, res, retryData)];
                  case 4:
                      err_1 = _a.sent();
                      return [2 /*return*/, retry(policy, request, response, retryData, err_1)];
                  case 5: return [3 /*break*/, 7];
                  case 6:
                      if (isAborted || requestError || !response) {
                          err = retryData.error ||
                              new RestError("Failed to send the request.", RestError.REQUEST_SEND_ERROR, response && response.status, response && response.request, response);
                          throw err;
                      }
                      else {
                          return [2 /*return*/, response];
                      }
                      _a.label = 7;
                  case 7: return [2 /*return*/];
              }
          });
      });
  }
  //# sourceMappingURL=exponentialRetryPolicy.js.map