text: // Copyright (c) Microsoft Corporation.
  // Licensed under the MIT license.
  import { __awaiter, __extends, __generator } from "tslib";
  import { BaseRequestPolicy } from "../policies/requestPolicy";
  import { Constants } from "../util/constants";
  import { HttpHeaders } from "../httpHeaders";
  import { ExpiringAccessTokenCache } from "../credentials/accessTokenCache";
  import { AccessTokenRefresher } from "../credentials/accessTokenRefresher";
  /**
   * The automated token refresh will only start to happen at the
   * expiration date minus the value of timeBetweenRefreshAttemptsInMs,
   * which is by default 30 seconds.
   */
  var timeBetweenRefreshAttemptsInMs = 30000;
  /**
   * Creates a new BearerTokenAuthenticationPolicy factory.
   *
   * @param credential - The TokenCredential implementation that can supply the bearer token.
   * @param scopes - The scopes for which the bearer token applies.
   */
  export function bearerTokenAuthenticationPolicy(credential, scopes) {
      var tokenCache = new ExpiringAccessTokenCache();
      var tokenRefresher = new AccessTokenRefresher(credential, scopes, timeBetweenRefreshAttemptsInMs);
      return {
          create: function (nextPolicy, options) {
              return new BearerTokenAuthenticationPolicy(nextPolicy, options, tokenCache, tokenRefresher);
          }
      };
  }
  /**
   *
   * Provides a RequestPolicy that can request a token from a TokenCredential
   * implementation and then apply it to the Authorization header of a request
   * as a Bearer token.
   *
   */
  var BearerTokenAuthenticationPolicy = /** @class */ (function (_super) {
      __extends(BearerTokenAuthenticationPolicy, _super);
      /**
       * Creates a new BearerTokenAuthenticationPolicy object.
       *
       * @param nextPolicy - The next RequestPolicy in the request pipeline.
       * @param options - Options for this RequestPolicy.
       * @param credential - The TokenCredential implementation that can supply the bearer token.
       * @param scopes - The scopes for which the bearer token applies.
       * @param tokenCache - The cache for the most recent AccessToken returned from the TokenCredential.
       */
      function BearerTokenAuthenticationPolicy(nextPolicy, options, tokenCache, tokenRefresher) {
          var _this = _super.call(this, nextPolicy, options) || this;
          _this.tokenCache = tokenCache;
          _this.tokenRefresher = tokenRefresher;
          return _this;
      }
      /**
       * Applies the Bearer token to the request through the Authorization header.
       */
      BearerTokenAuthenticationPolicy.prototype.sendRequest = function (webResource) {
          return __awaiter(this, void 0, void 0, function () {
              var token;
              return __generator(this, function (_a) {
                  switch (_a.label) {
                      case 0:
                          if (!webResource.headers)
                              webResource.headers = new HttpHeaders();
                          return [4 /*yield*/, this.getToken({
                                  abortSignal: webResource.abortSignal,
                                  tracingOptions: {
                                      spanOptions: webResource.spanOptions
                                  }
                              })];
                      case 1:
                          token = _a.sent();
                          webResource.headers.set(Constants.HeaderConstants.AUTHORIZATION, "Bearer " + token);
                          return [2 /*return*/, this._nextPolicy.sendRequest(webResource)];
                  }
              });
          });
      };
      /**
       * Attempts a token update if any other time related conditionals have been reached based on the tokenRefresher class.
       */
      BearerTokenAuthenticationPolicy.prototype.updateTokenIfNeeded = function (options) {
          return __awaiter(this, void 0, void 0, function () {
              var accessToken;
              return __generator(this, function (_a) {
                  switch (_a.label) {
                      case 0:
                          if (!this.tokenRefresher.isReady()) return [3 /*break*/, 2];
                          return [4 /*yield*/, this.tokenRefresher.refresh(options)];
                      case 1:
                          accessToken = _a.sent();
                          this.tokenCache.setCachedToken(accessToken);
                          _a.label = 2;
                      case 2: return [2 /*return*/];
                  }
              });
          });
      };
      BearerTokenAuthenticationPolicy.prototype.getToken = function (options) {
          return __awaiter(this, void 0, void 0, function () {
              var accessToken;
              return __generator(this, function (_a) {
                  switch (_a.label) {
                      case 0:
                          accessToken = this.tokenCache.getCachedToken();
                          if (!(accessToken === undefined)) return [3 /*break*/, 2];
                          return [4 /*yield*/, this.tokenRefresher.refresh(options)];
                      case 1:
                          // Waiting for the next refresh only if the cache is unable to retrieve the access token,
                          // which means that it has expired, or it has never been set.
                          accessToken = _a.sent();
                          this.tokenCache.setCachedToken(accessToken);
                          return [3 /*break*/, 3];
                      case 2:
                          // If we still have a cached access token,
                          // And any other time related conditionals have been reached based on the tokenRefresher class,
                          // then attempt to refresh without waiting.
                          this.updateTokenIfNeeded(options);
                          _a.label = 3;
                      case 3: return [2 /*return*/, accessToken ? accessToken.token : undefined];
                  }
              });
          });
      };
      return BearerTokenAuthenticationPolicy;
  }(BaseRequestPolicy));
  export { BearerTokenAuthenticationPolicy };
  //# sourceMappingURL=bearerTokenAuthenticationPolicy.js.map