text: Object.defineProperty(exports, "__esModule", { value: true });
  var tslib_1 = require("tslib");
  var utils_1 = require("@sentry/utils");
  /**
   * Holds additional event information. {@link Scope.applyToEvent} will be
   * called by the client before an event will be sent.
   */
  var Scope = /** @class */ (function () {
      function Scope() {
          /** Flag if notifiying is happening. */
          this._notifyingListeners = false;
          /** Callback for client to receive scope changes. */
          this._scopeListeners = [];
          /** Callback list that will be called after {@link applyToEvent}. */
          this._eventProcessors = [];
          /** Array of breadcrumbs. */
          this._breadcrumbs = [];
          /** User */
          this._user = {};
          /** Tags */
          this._tags = {};
          /** Extra */
          this._extra = {};
          /** Contexts */
          this._contexts = {};
      }
      /**
       * Inherit values from the parent scope.
       * @param scope to clone.
       */
      Scope.clone = function (scope) {
          var newScope = new Scope();
          if (scope) {
              newScope._breadcrumbs = tslib_1.__spread(scope._breadcrumbs);
              newScope._tags = tslib_1.__assign({}, scope._tags);
              newScope._extra = tslib_1.__assign({}, scope._extra);
              newScope._contexts = tslib_1.__assign({}, scope._contexts);
              newScope._user = scope._user;
              newScope._level = scope._level;
              newScope._span = scope._span;
              newScope._session = scope._session;
              newScope._transactionName = scope._transactionName;
              newScope._fingerprint = scope._fingerprint;
              newScope._eventProcessors = tslib_1.__spread(scope._eventProcessors);
          }
          return newScope;
      };
      /**
       * Add internal on change listener. Used for sub SDKs that need to store the scope.
       * @hidden
       */
      Scope.prototype.addScopeListener = function (callback) {
          this._scopeListeners.push(callback);
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.addEventProcessor = function (callback) {
          this._eventProcessors.push(callback);
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.setUser = function (user) {
          this._user = user || {};
          if (this._session) {
              this._session.update({ user: user });
          }
          this._notifyScopeListeners();
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.getUser = function () {
          return this._user;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.setTags = function (tags) {
          this._tags = tslib_1.__assign(tslib_1.__assign({}, this._tags), tags);
          this._notifyScopeListeners();
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.setTag = function (key, value) {
          var _a;
          this._tags = tslib_1.__assign(tslib_1.__assign({}, this._tags), (_a = {}, _a[key] = value, _a));
          this._notifyScopeListeners();
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.setExtras = function (extras) {
          this._extra = tslib_1.__assign(tslib_1.__assign({}, this._extra), extras);
          this._notifyScopeListeners();
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.setExtra = function (key, extra) {
          var _a;
          this._extra = tslib_1.__assign(tslib_1.__assign({}, this._extra), (_a = {}, _a[key] = extra, _a));
          this._notifyScopeListeners();
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.setFingerprint = function (fingerprint) {
          this._fingerprint = fingerprint;
          this._notifyScopeListeners();
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.setLevel = function (level) {
          this._level = level;
          this._notifyScopeListeners();
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.setTransactionName = function (name) {
          this._transactionName = name;
          this._notifyScopeListeners();
          return this;
      };
      /**
       * Can be removed in major version.
       * @deprecated in favor of {@link this.setTransactionName}
       */
      Scope.prototype.setTransaction = function (name) {
          return this.setTransactionName(name);
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.setContext = function (key, context) {
          var _a;
          if (context === null) {
              // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
              delete this._contexts[key];
          }
          else {
              this._contexts = tslib_1.__assign(tslib_1.__assign({}, this._contexts), (_a = {}, _a[key] = context, _a));
          }
          this._notifyScopeListeners();
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.setSpan = function (span) {
          this._span = span;
          this._notifyScopeListeners();
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.getSpan = function () {
          return this._span;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.getTransaction = function () {
          var _a, _b, _c, _d;
          // often, this span will be a transaction, but it's not guaranteed to be
          var span = this.getSpan();
          // try it the new way first
          if ((_a = span) === null || _a === void 0 ? void 0 : _a.transaction) {
              return (_b = span) === null || _b === void 0 ? void 0 : _b.transaction;
          }
          // fallback to the old way (known bug: this only finds transactions with sampled = true)
          if ((_d = (_c = span) === null || _c === void 0 ? void 0 : _c.spanRecorder) === null || _d === void 0 ? void 0 : _d.spans[0]) {
              return span.spanRecorder.spans[0];
          }
          // neither way found a transaction
          return undefined;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.setSession = function (session) {
          if (!session) {
              delete this._session;
          }
          else {
              this._session = session;
          }
          this._notifyScopeListeners();
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.getSession = function () {
          return this._session;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.update = function (captureContext) {
          if (!captureContext) {
              return this;
          }
          if (typeof captureContext === 'function') {
              var updatedScope = captureContext(this);
              return updatedScope instanceof Scope ? updatedScope : this;
          }
          if (captureContext instanceof Scope) {
              this._tags = tslib_1.__assign(tslib_1.__assign({}, this._tags), captureContext._tags);
              this._extra = tslib_1.__assign(tslib_1.__assign({}, this._extra), captureContext._extra);
              this._contexts = tslib_1.__assign(tslib_1.__assign({}, this._contexts), captureContext._contexts);
              if (captureContext._user && Object.keys(captureContext._user).length) {
                  this._user = captureContext._user;
              }
              if (captureContext._level) {
                  this._level = captureContext._level;
              }
              if (captureContext._fingerprint) {
                  this._fingerprint = captureContext._fingerprint;
              }
          }
          else if (utils_1.isPlainObject(captureContext)) {
              // eslint-disable-next-line no-param-reassign
              captureContext = captureContext;
              this._tags = tslib_1.__assign(tslib_1.__assign({}, this._tags), captureContext.tags);
              this._extra = tslib_1.__assign(tslib_1.__assign({}, this._extra), captureContext.extra);
              this._contexts = tslib_1.__assign(tslib_1.__assign({}, this._contexts), captureContext.contexts);
              if (captureContext.user) {
                  this._user = captureContext.user;
              }
              if (captureContext.level) {
                  this._level = captureContext.level;
              }
              if (captureContext.fingerprint) {
                  this._fingerprint = captureContext.fingerprint;
              }
          }
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.clear = function () {
          this._breadcrumbs = [];
          this._tags = {};
          this._extra = {};
          this._user = {};
          this._contexts = {};
          this._level = undefined;
          this._transactionName = undefined;
          this._fingerprint = undefined;
          this._span = undefined;
          this._session = undefined;
          this._notifyScopeListeners();
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.addBreadcrumb = function (breadcrumb, maxBreadcrumbs) {
          var mergedBreadcrumb = tslib_1.__assign({ timestamp: utils_1.dateTimestampInSeconds() }, breadcrumb);
          this._breadcrumbs =
              maxBreadcrumbs !== undefined && maxBreadcrumbs >= 0
                  ? tslib_1.__spread(this._breadcrumbs, [mergedBreadcrumb]).slice(-maxBreadcrumbs)
                  : tslib_1.__spread(this._breadcrumbs, [mergedBreadcrumb]);
          this._notifyScopeListeners();
          return this;
      };
      /**
       * @inheritDoc
       */
      Scope.prototype.clearBreadcrumbs = function () {
          this._breadcrumbs = [];
          this._notifyScopeListeners();
          return this;
      };
      /**
       * Applies the current context and fingerprint to the event.
       * Note that breadcrumbs will be added by the client.
       * Also if the event has already breadcrumbs on it, we do not merge them.
       * @param event Event
       * @param hint May contain additional informartion about the original exception.
       * @hidden
       */
      Scope.prototype.applyToEvent = function (event, hint) {
          if (this._extra && Object.keys(this._extra).length) {
              event.extra = tslib_1.__assign(tslib_1.__assign({}, this._extra), event.extra);
          }
          if (this._tags && Object.keys(this._tags).length) {
              event.tags = tslib_1.__assign(tslib_1.__assign({}, this._tags), event.tags);
          }
          if (this._user && Object.keys(this._user).length) {
              event.user = tslib_1.__assign(tslib_1.__assign({}, this._user), event.user);
          }
          if (this._contexts && Object.keys(this._contexts).length) {
              event.contexts = tslib_1.__assign(tslib_1.__assign({}, this._contexts), event.contexts);
          }
          if (this._level) {
              event.level = this._level;
          }
          if (this._transactionName) {
              event.transaction = this._transactionName;
          }
          // We want to set the trace context for normal events only if there isn't already
          // a trace context on the event. There is a product feature in place where we link
          // errors with transaction and it relys on that.
          if (this._span) {
              event.contexts = tslib_1.__assign({ trace: this._span.getTraceContext() }, event.contexts);
          }
          this._applyFingerprint(event);
          event.breadcrumbs = tslib_1.__spread((event.breadcrumbs || []), this._breadcrumbs);
          event.breadcrumbs = event.breadcrumbs.length > 0 ? event.breadcrumbs : undefined;
          return this._notifyEventProcessors(tslib_1.__spread(getGlobalEventProcessors(), this._eventProcessors), event, hint);
      };
      /**
       * This will be called after {@link applyToEvent} is finished.
       */
      Scope.prototype._notifyEventProcessors = function (processors, event, hint, index) {
          var _this = this;
          if (index === void 0) { index = 0; }
          return new utils_1.SyncPromise(function (resolve, reject) {
              var processor = processors[index];
              if (event === null || typeof processor !== 'function') {
                  resolve(event);
              }
              else {
                  var result = processor(tslib_1.__assign({}, event), hint);
                  if (utils_1.isThenable(result)) {
                      result
                          .then(function (final) { return _this._notifyEventProcessors(processors, final, hint, index + 1).then(resolve); })
                          .then(null, reject);
                  }
                  else {
                      _this._notifyEventProcessors(processors, result, hint, index + 1)
                          .then(resolve)
                          .then(null, reject);
                  }
              }
          });
      };
      /**
       * This will be called on every set call.
       */
      Scope.prototype._notifyScopeListeners = function () {
          var _this = this;
          if (!this._notifyingListeners) {
              this._notifyingListeners = true;
              setTimeout(function () {
                  _this._scopeListeners.forEach(function (callback) {
                      callback(_this);
                  });
                  _this._notifyingListeners = false;
              });
          }
      };
      /**
       * Applies fingerprint from the scope to the event if there's one,
       * uses message if there's one instead or get rid of empty fingerprint
       */
      Scope.prototype._applyFingerprint = function (event) {
          // Make sure it's an array first and we actually have something in place
          event.fingerprint = event.fingerprint
              ? Array.isArray(event.fingerprint)
                  ? event.fingerprint
                  : [event.fingerprint]
              : [];
          // If we have something on the scope, then merge it with event
          if (this._fingerprint) {
              event.fingerprint = event.fingerprint.concat(this._fingerprint);
          }
          // If we have no data at all, remove empty array default
          if (event.fingerprint && !event.fingerprint.length) {
              delete event.fingerprint;
          }
      };
      return Scope;
  }());
  exports.Scope = Scope;
  /**
   * Retruns the global event processors.
   */
  function getGlobalEventProcessors() {
      var global = utils_1.getGlobalObject();
      global.__SENTRY__ = global.__SENTRY__ || {};
      global.__SENTRY__.globalEventProcessors = global.__SENTRY__.globalEventProcessors || [];
      return global.__SENTRY__.globalEventProcessors;
  }
  /**
   * Add a EventProcessor to be kept globally.
   * @param callback EventProcessor to add
   */
  function addGlobalEventProcessor(callback) {
      getGlobalEventProcessors().push(callback);
  }
  exports.addGlobalEventProcessor = addGlobalEventProcessor;
  //# sourceMappingURL=scope.js.map