import { SetupContext as n } from "./SetupContext.js";
import { AuthSessionSpecification as h } from "./AuthSessionSpecification.js";
import { createErrorContainer as a } from "../../../primitives/auxiliary/errorContainer/main.js";
import { SessionContext as _ } from "../../../primitives/context/session/SessionContext.js";
import { createPromisor as f } from "../../../primitives/async/promisor/main.js";
import { createWatchlist as c } from "../../../primitives/reactive/watchlist/main.js";
import { EVT_SESSION_EXPIRED as l, EVT_SESSION_READY as S, ERR_SESSION_REFRESH_ABORTED as p } from "../../../primitives/context/session/constants.js";
import { boolOrTrue as C, boolOrFalse as u } from "../../../utils/value/bool.js";
import { isFunction as m } from "../../../utils/value/is.js";
class F {
  _canSkipSessionRefresh = !1;
  _refreshPromisorSignal;
  _sessionIsFrozen = !1;
  _errorContainer = a();
  _specification = new h();
  _sessionContext = new _(this._specification);
  _setupContext = new n(this._sessionContext);
  _refreshPromisor = f(async (s, i = !1) => {
    let t = !this._refreshPromisorSignal, r = this._refreshPromisorSignal === (this._refreshPromisorSignal = s);
    const e = u(i) && this._canSkipSessionRefresh;
    t && (t = !1, this._errorContainer.reset(), this._onAuthStateChanged());
    try {
      await (e ? this._setupContext : this._sessionContext).refresh(s).finally(() => r = this._refreshPromisorSignal === s);
    } catch (o) {
      if (!r) return;
      !s.aborted && (e || o !== p) && this._errorContainer.set(o), t = !e;
    } finally {
      (t || e && r) && (this._refreshPromisorSignal = void 0, this._onAuthStateChanged());
    }
  });
  _watchlist = c({
    endpoints: () => this._setupContext.endpoints,
    extraConfig: () => this._setupContext.extraConfig,
    hasError: () => this._errorContainer.hasError,
    isExpired: () => this._sessionContext.isExpired,
    isFrozen: () => this._sessionIsFrozen,
    refreshing: () => !!this._refreshPromisorSignal
  });
  freeze = () => {
    this._sessionIsFrozen = !0, this._watchlist.on.resume = void 0, this._watchlist.cancelSubscriptions();
  };
  http = this._sessionContext.http.bind(this._sessionContext, null);
  refresh = this._refresh.bind(this);
  subscribe = this._watchlist.subscribe;
  constructor() {
    this._watchlist.on.resume = () => {
      const s = [
        this._sessionContext.on(l, () => {
          this._canSkipSessionRefresh = !1, this._onAuthStateChanged();
        }),
        this._sessionContext.on(S, () => {
          this._refresh(this._canSkipSessionRefresh = !0);
        })
      ];
      this._watchlist.on.idle = () => {
        this._watchlist.on.idle = void 0, s.forEach((i) => i()), s.length = 0;
      }, !this.context.refreshing && C(this.context.isExpired) && this._refresh();
    };
  }
  get context() {
    return this._watchlist.snapshot;
  }
  set loadingContext(s) {
    this._setupContext.loadingContext = s;
  }
  set analyticsPayload(s) {
    this._setupContext.analyticsPayload = s;
  }
  set analyticsEnabled(s) {
    this._setupContext.analyticsEnabled = s;
  }
  set errorHandler(s) {
    this._specification.errorHandler = s;
  }
  set onSessionCreate(s) {
    this._specification.onSessionCreate !== s && (this._specification.onSessionCreate = s, this._refreshPromisorSignal && m(this._specification.onSessionCreate) && (this._canSkipSessionRefresh = !1, this._refresh()));
  }
  _onAuthStateChanged() {
    this._watchlist.requestNotification();
  }
  _refresh(s = !1) {
    this._refreshPromisor(s);
  }
}
export {
  F as AuthSession
};
