import { unreachable } from "../../../shared/src/asserts.js";
import { Subscribable } from "../../../shared/src/subscribable.js";
import { PushFailed, TransformFailed } from "../../../zero-protocol/src/error-kind-enum.js";
import { NoSocketOrigin } from "./client-error-kind-enum.js";
import { Disconnected, Connecting, NeedsAuth, Error, Connected, Closed } from "./connection-status-enum.js";
class ConnectionImpl {
  #connectionManager;
  #lc;
  #source;
  #setAuth;
  constructor(connectionManager, lc, setAuth) {
    this.#connectionManager = connectionManager;
    this.#lc = lc;
    this.#source = new ConnectionSource(connectionManager);
    this.#setAuth = setAuth;
  }
  get state() {
    return this.#source;
  }
  async connect(opts) {
    const lc = this.#lc.withContext("connect");
    if (opts && "auth" in opts) {
      lc.debug?.("Updating auth credential from connect()");
      this.#setAuth(opts.auth);
    }
    if (this.#connectionManager.state.name === Disconnected && this.#connectionManager.state.reason.kind === NoSocketOrigin) {
      lc.error?.(
        "connect() called but the connection is disconnected due to a missing cacheURL. No reconnect will be attempted."
      );
      return;
    }
    if (!this.#connectionManager.isInTerminalState()) {
      lc.debug?.(
        "connect() called but not in a terminal state. Current state:",
        this.#connectionManager.state.name
      );
      return;
    }
    lc.info?.(
      `Resuming connection from state: ${this.#connectionManager.state.name}`
    );
    this.#connectionManager.requestConnect();
    if (this.#connectionManager.state.name === Connecting) {
      return;
    }
    await this.#connectionManager.waitForStateChange();
  }
}
class ConnectionSource extends Subscribable {
  #state;
  constructor(connectionManager) {
    super();
    this.#state = this.#mapConnectionManagerState(connectionManager.state);
    connectionManager.subscribe((state) => {
      this.#state = this.#mapConnectionManagerState(state);
      this.notify(this.#state);
    });
  }
  get current() {
    return this.#state;
  }
  #mapConnectionManagerState(state) {
    switch (state.name) {
      case Closed:
        return {
          name: "closed",
          reason: state.reason.message
        };
      case Connected:
        return {
          name: "connected"
        };
      case Connecting:
        return {
          name: "connecting",
          ...state.reason?.message ? { reason: state.reason.message } : {}
        };
      case Disconnected:
        return {
          name: "disconnected",
          reason: state.reason.message
        };
      case Error:
        return {
          name: "error",
          reason: state.reason.message
        };
      case NeedsAuth:
        return {
          name: "needs-auth",
          reason: state.reason.errorBody.kind === PushFailed ? {
            type: "mutate",
            status: state.reason.errorBody.status,
            ...state.reason.errorBody.bodyPreview ? { body: state.reason.errorBody.bodyPreview } : {}
          } : state.reason.errorBody.kind === TransformFailed ? {
            type: "query",
            status: state.reason.errorBody.status,
            ...state.reason.errorBody.bodyPreview ? { body: state.reason.errorBody.bodyPreview } : {}
          } : {
            type: "zero-cache",
            reason: state.reason.message
          }
        };
      default:
        unreachable();
    }
  }
}
export {
  ConnectionImpl,
  ConnectionSource
};
//# sourceMappingURL=connection.js.map
