import EventEmitter from "@racletteCore/lib/eventEmitter"
import type { Socket } from "socket.io-client"
import type { LoggerInstance } from "@racletteCore/lib/logger"
import type { PluginApi } from "@racletteOrchestrator"
import type { PluginSocketApi } from "../types"
import type { RegisteredPlugin } from "@racletteCore"

export const wrapLogApi = (
  $log: LoggerInstance,
  pluginKey: string,
  pluginApi: Partial<PluginApi>,
): Partial<PluginApi> => {
  if ($log && !pluginApi.$log) {
    pluginApi.$log = $log.plugin(pluginKey)
  }
  return pluginApi
}

export const wrapFileApi = (
  $file: any,
  pluginApi: Partial<PluginApi>,
): Partial<PluginApi> => {
  if ($file && !pluginApi.$file) {
    pluginApi.$file = $file
  }
  return pluginApi
}

export const wrapEventbusApi = (
  plugin: RegisteredPlugin,
  $eventbus: any,
  pluginApi: Partial<PluginApi>,
): any => {
  if ($eventbus && !pluginApi.$eventbus) {
    const $pluginEventbus = new EventEmitter(false, false)
    $pluginEventbus.global = {
      on: (event: string, listener: Function) => {
        return $eventbus.on(event, listener)
      },
      once: (event: string, listener: Function) => {
        return $eventbus.once(event, listener)
      },
      emit: (event: string, payload: object) => {
        return $eventbus.emit(event, {
          sender: plugin.pluginKey,
          data: payload,
        })
      },
      isValid: (event: string) => {
        return $eventbus.isValid(event)
      },
    }
    return $pluginEventbus
  }
  return pluginApi
}

export const wrapSocketApi = (
  plugin: RegisteredPlugin,
  $socket: Socket,
): PluginSocketApi => {
  const socketApi: PluginSocketApi = {
    registeredListeners: [],
    on: (eventName: string, handlerFn: Function) => {
      const channelName = `${plugin.pluginKey}--${eventName}`
      socketApi.registeredListeners.push({ channelName, handlerFn })
      return $socket.on(channelName, handlerFn)
    },
    off: (eventIdentity: string, handlerFn: Function) => {
      return $socket.off(eventIdentity, handlerFn)
    },
    emit: (eventName: string, eventPayload: any) => {
      return $socket.emit(eventName, eventPayload)
    },
    once: (eventName: string, handlerFn: Function) => {
      return $socket.once(eventName, handlerFn)
    },
  }

  return socketApi
}
