import SocketIO from 'socket.io';
import {EmitHistoryPacket, EmitPacket} from './common.types';
import Queue from '../../tools/queue';

/**
 * Returns socket sticky session ID
 * @param socket native socket.io socket
 * @returns sticky session ID
 */
export function getSocketStickySessionId(socket: SocketIO.Socket): string {
  return socket.handshake.query['stickySocketConnectionId'] || socket.id; // eslint-disable-line dot-notation
}

/**
 * Returns whether a socket supports sticky socket protocol
 * @param socket native socket.io socket
 * @returns whether supports the protocol
 */
export function supportsStickySocketProtocol(socket: SocketIO.Socket): boolean {
  return !!socket.handshake.query['stickySocketConnectionId']; // eslint-disable-line dot-notation
}

/**
 * Returns client socket.io socket transport
 * @param socket native socket.io socket
 * @returns current transport name
 */
export function getClientSocketIoTransportName(socket: SocketIOClient.Socket): string {
  return (socket.io as any).engine.transport.name;
}

/**
 * Destroys underlying socket of a client socket, using socket.io internals. The socket must have `websocket` transport
 * @param socket native socket.io socket
 * @param err optional error
 */
export function destroyInternalClientSocket(socket: SocketIOClient.Socket, err?: Error) {
  (socket.io as any).engine.transport.ws._socket.destroy(err);
}

/**
 * Sends history events to a socket
 * @param socket socket to send to
 * @param history history to send from (will be modified)
 * @param startIndex start packet index to stream from
 */
export function sendHistory(
  socket: SocketIOClient.Socket | SocketIO.Socket, history: Queue<EmitHistoryPacket>, startIndex: number
) {
  while (history.length && history.front().index < startIndex) {
    history.shift();
  }
  for (let packet of history) {
    packet.time = new Date();
    socket.emit(packet.event, {
      index: packet.index,
      data: packet.data
    } satisfies EmitPacket);
  }
}
