// WebSocket bridge for the Rudder Unity SDK (JsWebSocketAdapter).
// Implements the __Internal__ externals declared in Realtime/JsWebSocketAdapter.cs:
//   RudderWebSocketCreate(gameObjectName, url)
//   RudderWebSocketSend(gameObjectName, data, length)
//   RudderWebSocketClose(gameObjectName)
// Events are routed back to the bridge GameObject via SendMessage:
//   OnOpen(string), OnMessage(string base64), OnClose(string), OnError(string)

var RudderWebSockets = {};

function RudderWebSocketBase64(bytes) {
  var chunks = [];
  var chunkSize = 0x8000;
  for (var i = 0; i < bytes.length; i += chunkSize) {
    chunks.push(String.fromCharCode.apply(null, bytes.subarray(i, i + chunkSize)));
  }
  return btoa(chunks.join(''));
}

mergeInto(LibraryManager.library, {
  RudderWebSocketCreate: function (gameObjectName, url) {
    var name = UTF8ToString(gameObjectName);
    var socket = new WebSocket(UTF8ToString(url));
    socket.binaryType = 'arraybuffer';
    RudderWebSockets[name] = socket;

    socket.onopen = function () {
      SendMessage(name, 'OnOpen', 'opened');
    };

    socket.onmessage = function (event) {
      var bytes;
      if (typeof event.data === 'string') {
        // Text frame: UTF-8 encode, then base64 (the C# side decodes base64 to bytes).
        bytes = new TextEncoder().encode(event.data);
      } else {
        bytes = new Uint8Array(event.data);
      }
      SendMessage(name, 'OnMessage', RudderWebSocketBase64(bytes));
    };

    socket.onerror = function () {
      SendMessage(name, 'OnError', 'WebSocket error');
    };

    socket.onclose = function () {
      delete RudderWebSockets[name];
      SendMessage(name, 'OnClose', 'closed');
    };
  },

  RudderWebSocketSend: function (gameObjectName, data, length) {
    var socket = RudderWebSockets[UTF8ToString(gameObjectName)];
    if (!socket || socket.readyState !== WebSocket.OPEN) return;
    socket.send(HEAPU8.subarray(data, data + length));
  },

  RudderWebSocketClose: function (gameObjectName) {
    var name = UTF8ToString(gameObjectName);
    var socket = RudderWebSockets[name];
    if (socket) {
      delete RudderWebSockets[name];
      socket.close();
    }
  }
});
