'use client';
import { _ as _classPrivateFieldLooseBase, a as _classPrivateFieldLooseKey } from './protobuf-OcbVtxg1.js';
import { F as FoxgloveClient } from './FoxgloveServer-Da9kV1cr.js';
import { L as Logger } from './logger-Bqy1nuLj.js';
import { F as FoxgloveCommunicator } from './communicator-Dh2aL-rj.js';
import 'ms';
import './encoding-jXImCIb4.js';

const logger = Logger.getLogger();
var _wasOpen = /*#__PURE__*/_classPrivateFieldLooseKey("wasOpen");
var _alive = /*#__PURE__*/_classPrivateFieldLooseKey("alive");
var _reconnecting = /*#__PURE__*/_classPrivateFieldLooseKey("reconnecting");
var _reconnectAttempts = /*#__PURE__*/_classPrivateFieldLooseKey("reconnectAttempts");
var _maxReconnectAttempts = /*#__PURE__*/_classPrivateFieldLooseKey("maxReconnectAttempts");
var _ws = /*#__PURE__*/_classPrivateFieldLooseKey("ws");
var _client = /*#__PURE__*/_classPrivateFieldLooseKey("client");
var _subscriptions = /*#__PURE__*/_classPrivateFieldLooseKey("subscriptions");
var _createWs = /*#__PURE__*/_classPrivateFieldLooseKey("createWs");
var _createClient = /*#__PURE__*/_classPrivateFieldLooseKey("createClient");
var _handleMessages = /*#__PURE__*/_classPrivateFieldLooseKey("handleMessages");
class WsWorker extends FoxgloveCommunicator {
  send(message) {
    self.postMessage(message);
  }
  sendWithTransfer(message, transfer) {
    self.postMessage(message, transfer);
  }
  sendServiceCallRequest(request) {
    _classPrivateFieldLooseBase(this, _client)[_client].sendServiceCallRequest(request);
  }
  isReady() {
    return _classPrivateFieldLooseBase(this, _ws)[_ws].readyState === _classPrivateFieldLooseBase(this, _ws)[_ws].OPEN;
  }
  constructor(wsUrl) {
    super();
    Object.defineProperty(this, _handleMessages, {
      value: _handleMessages2
    });
    Object.defineProperty(this, _createClient, {
      value: _createClient2
    });
    Object.defineProperty(this, _createWs, {
      value: _createWs2
    });
    Object.defineProperty(this, _wasOpen, {
      writable: true,
      value: false
    });
    Object.defineProperty(this, _alive, {
      writable: true,
      value: true
    });
    Object.defineProperty(this, _reconnecting, {
      writable: true,
      value: false
    });
    Object.defineProperty(this, _reconnectAttempts, {
      writable: true,
      value: 0
    });
    Object.defineProperty(this, _maxReconnectAttempts, {
      writable: true,
      value: 10
    });
    Object.defineProperty(this, _ws, {
      writable: true,
      value: void 0
    });
    Object.defineProperty(this, _client, {
      writable: true,
      value: void 0
    });
    Object.defineProperty(this, _subscriptions, {
      writable: true,
      value: new Map()
    });
    try {
      _classPrivateFieldLooseBase(this, _createWs)[_createWs](wsUrl, this.handleReconnect.bind(this));
      _classPrivateFieldLooseBase(this, _createClient)[_createClient]();
      _classPrivateFieldLooseBase(this, _handleMessages)[_handleMessages]();
    } catch (error) {
      // try-catch is needed to catch `Mixed Content` errors in Chrome, where the client
      // attempts to load `ws://` from `https://`. (Safari would catch these in `ws.onerror`
      // but with `undefined` as an error.)
      this.send({
        type: "error",
        error: error !== null && error !== void 0 ? error : {
          message: "Insecure WebSocket connection"
        }
      });
    }
  }
  subscribe(topics) {
    const channels = this.getPublicChannels().filter(publicChannel => topics.includes(publicChannel.topic));
    for (const channel of channels) {
      const subscription = _classPrivateFieldLooseBase(this, _client)[_client].subscribe(channel.id);
      _classPrivateFieldLooseBase(this, _subscriptions)[_subscriptions].set(subscription, {
        topic: channel.topic,
        schema: channel.schemaName,
        kind: channel.kind
      });
    }
  }
  unsubscribe(topics) {
    const subscriptionIds = [..._classPrivateFieldLooseBase(this, _subscriptions)[_subscriptions].entries()].filter(([_id, data]) => topics.includes(data.topic)).map(subscription => subscription[0]);
    for (const subscriptionId of subscriptionIds) {
      _classPrivateFieldLooseBase(this, _subscriptions)[_subscriptions].delete(subscriptionId);
      _classPrivateFieldLooseBase(this, _client)[_client].unsubscribe(subscriptionId);
    }
  }
  callService(args) {
    super.callService(args);
  }
  close() {
    _classPrivateFieldLooseBase(this, _alive)[_alive] = false;
    _classPrivateFieldLooseBase(this, _client)[_client].close();
    _classPrivateFieldLooseBase(this, _ws)[_ws].close();
  }
}
function _createWs2(url, onReconnect) {
  if (!_classPrivateFieldLooseBase(this, _alive)[_alive]) {
    return;
  }
  _classPrivateFieldLooseBase(this, _ws)[_ws] = new WebSocket(url, FoxgloveClient.SUPPORTED_SUBPROTOCOL);
  _classPrivateFieldLooseBase(this, _ws)[_ws].binaryType = "arraybuffer";
  const reconnect = () => {
    if (_classPrivateFieldLooseBase(this, _alive)[_alive] && !_classPrivateFieldLooseBase(this, _reconnecting)[_reconnecting]) {
      _classPrivateFieldLooseBase(this, _reconnectAttempts)[_reconnectAttempts]++;
      if (_classPrivateFieldLooseBase(this, _reconnectAttempts)[_reconnectAttempts] > _classPrivateFieldLooseBase(this, _maxReconnectAttempts)[_maxReconnectAttempts]) {
        _classPrivateFieldLooseBase(this, _alive)[_alive] = false;
        this.send({
          type: "error",
          error: {
            message: `Failed to reconnect after ${_classPrivateFieldLooseBase(this, _maxReconnectAttempts)[_maxReconnectAttempts]} attempts`
          }
        });
        return;
      }
      _classPrivateFieldLooseBase(this, _reconnecting)[_reconnecting] = true;
      onReconnect();
      setTimeout(() => {
        _classPrivateFieldLooseBase(this, _createWs)[_createWs](url, onReconnect);
        _classPrivateFieldLooseBase(this, _createClient)[_createClient]();
        _classPrivateFieldLooseBase(this, _handleMessages)[_handleMessages]();
        _classPrivateFieldLooseBase(this, _reconnecting)[_reconnecting] = false;
      }, 1000);
    }
  };
  _classPrivateFieldLooseBase(this, _ws)[_ws].addEventListener('error', reconnect);
  _classPrivateFieldLooseBase(this, _ws)[_ws].addEventListener('close', reconnect);
}
function _createClient2() {
  _classPrivateFieldLooseBase(this, _client)[_client] = new FoxgloveClient({
    ws: _classPrivateFieldLooseBase(this, _ws)[_ws]
  });
  _classPrivateFieldLooseBase(this, _client)[_client].on("open", () => {
    _classPrivateFieldLooseBase(this, _wasOpen)[_wasOpen] = true;
    _classPrivateFieldLooseBase(this, _reconnectAttempts)[_reconnectAttempts] = 0; // Reset counter on successful connection
    this.send({
      type: "open"
    });
  });
  _classPrivateFieldLooseBase(this, _client)[_client].on("close", () => {
    if (_classPrivateFieldLooseBase(this, _wasOpen)[_wasOpen]) {
      this.send({
        type: "close"
      });
    }
  });
  _classPrivateFieldLooseBase(this, _client)[_client].on("error", error => {
    if (_classPrivateFieldLooseBase(this, _wasOpen)[_wasOpen]) {
      this.send({
        type: "error",
        error
      });
    }
  });
  _classPrivateFieldLooseBase(this, _client)[_client].on("message", ({
    subscriptionId,
    data
  }) => {
    const subscription = _classPrivateFieldLooseBase(this, _subscriptions)[_subscriptions].get(subscriptionId);
    if (subscription) {
      this.handleGenericMessage(subscription.topic, subscription.schema, data);
    }
  });
}
function _handleMessages2() {
  _classPrivateFieldLooseBase(this, _client)[_client].on("advertise", this.handleChannelsAdvertisement.bind(this));
  _classPrivateFieldLooseBase(this, _client)[_client].on("unadvertise", this.handleChannelsUnadvertisement.bind(this));
  _classPrivateFieldLooseBase(this, _client)[_client].on("advertiseServices", this.handleServicesAdvertisement.bind(this));
  _classPrivateFieldLooseBase(this, _client)[_client].on("unadvertiseServices", this.handleServicesUnadvertisement.bind(this));
  _classPrivateFieldLooseBase(this, _client)[_client].on("serviceCallResponse", this.handleServiceResponse.bind(this));
}
let wsWorker = null;
self.addEventListener('message', async event => {
  const {
    type,
    data
  } = event.data;
  if (type !== 'open' && !wsWorker) {
    logger.warn(`WS Worker Error: Requested ${type} before open`);
    return;
  }
  switch (type) {
    case "open":
      wsWorker = new WsWorker('wsUrl' in data ? data.wsUrl : '');
      break;
    case "close":
      wsWorker.close();
      break;
    case "call_service":
      wsWorker.callService(data);
      break;
    case 'subscribe':
      wsWorker.subscribe(data);
      break;
    case 'unsubscribe':
      wsWorker.unsubscribe(data);
      break;
  }
});

export { WsWorker };
