var __defProp = Object.defineProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, {
      get: all[name],
      enumerable: true,
      configurable: true,
      set: (newValue) => all[name] = () => newValue
    });
};
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);

// src/remote/client.ts
class RemoteEngine {
  ws = null;
  url;
  state = "disconnected";
  options;
  reconnectAttempts = 0;
  reconnectTimer = null;
  patchCallbacks = [];
  stateCallbacks = [];
  connectionCallbacks = [];
  disconnectionCallbacks = [];
  errorCallbacks = [];
  currentState = null;
  currentRevision = 0;
  moduleName = "";
  constructor(url, options = {}) {
    this.url = url;
    this.options = {
      autoReconnect: options.autoReconnect ?? true,
      reconnectInterval: options.reconnectInterval ?? 3000,
      maxReconnectAttempts: options.maxReconnectAttempts ?? 10
    };
  }
  async connect() {
    if (this.state === "connected" || this.state === "connecting") {
      return;
    }
    this.state = "connecting";
    return new Promise((resolve, reject) => {
      try {
        this.ws = new WebSocket(this.url);
        this.ws.onopen = () => {
          this.state = "connected";
          this.reconnectAttempts = 0;
          this.connectionCallbacks.forEach((cb) => cb());
          resolve();
        };
        this.ws.onmessage = (event) => {
          this.handleMessage(event.data);
        };
        this.ws.onerror = () => {
          this.state = "error";
          const error = new Error("WebSocket error");
          this.errorCallbacks.forEach((cb) => cb(error));
          reject(error);
        };
        this.ws.onclose = () => {
          this.state = "disconnected";
          this.disconnectionCallbacks.forEach((cb) => cb());
          this.attemptReconnect();
        };
      } catch (error) {
        this.state = "error";
        reject(error);
      }
    });
  }
  disconnect() {
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }
    if (this.ws) {
      this.ws.close();
      this.ws = null;
    }
    this.state = "disconnected";
  }
  dispatchAction(action, payload) {
    if (this.state !== "connected" || !this.ws) {
      console.warn("Cannot dispatch action: not connected");
      return;
    }
    const message = {
      type: "dispatchAction",
      module: this.moduleName,
      action,
      payload
    };
    this.ws.send(JSON.stringify(message));
  }
  onPatches(callback) {
    this.patchCallbacks.push(callback);
    return this;
  }
  onStateUpdate(callback) {
    this.stateCallbacks.push(callback);
    return this;
  }
  onConnect(callback) {
    this.connectionCallbacks.push(callback);
    return this;
  }
  onDisconnect(callback) {
    this.disconnectionCallbacks.push(callback);
    return this;
  }
  onError(callback) {
    this.errorCallbacks.push(callback);
    return this;
  }
  getConnectionState() {
    return this.state;
  }
  getCurrentState() {
    return this.currentState;
  }
  getRevision() {
    return this.currentRevision;
  }
  handleMessage(data) {
    try {
      const message = JSON.parse(data);
      switch (message.type) {
        case "initialTree":
          this.handleInitialTree(message);
          break;
        case "patch":
          this.handlePatch(message);
          break;
        case "stateUpdate":
          this.currentState = message.state;
          this.stateCallbacks.forEach((cb) => cb(message.state));
          break;
      }
    } catch (error) {
      console.error("Error handling remote message:", error);
      this.errorCallbacks.forEach((cb) => cb(error instanceof Error ? error : new Error(String(error))));
    }
  }
  handleInitialTree(message) {
    this.moduleName = message.module;
    this.currentState = message.state;
    this.currentRevision = message.revision;
    if (message.patches.length > 0) {
      this.patchCallbacks.forEach((cb) => cb(message.patches));
    }
    this.stateCallbacks.forEach((cb) => cb(message.state));
  }
  handlePatch(message) {
    if (message.revision <= this.currentRevision) {
      console.warn(`Out of order patch: expected > ${this.currentRevision}, got ${message.revision}`);
      return;
    }
    this.currentRevision = message.revision;
    if (message.patches.length > 0) {
      this.patchCallbacks.forEach((cb) => cb(message.patches));
    }
  }
  attemptReconnect() {
    if (!this.options.autoReconnect) {
      return;
    }
    if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
      console.error("Max reconnection attempts reached");
      return;
    }
    this.reconnectAttempts++;
    console.log(`Attempting to reconnect (${this.reconnectAttempts}/${this.options.maxReconnectAttempts})...`);
    this.reconnectTimer = setTimeout(() => {
      this.connect().catch((error) => {
        console.error("Reconnection failed:", error);
      });
    }, this.options.reconnectInterval);
  }
}
export {
  RemoteEngine
};

//# debugId=2AAF271D9A6427D964756E2164756E21
