const {createSocks5ProxyServer, EVENTS} = require('@applitools/eg-socks5-proxy-server')

module.exports = async function ({port, logger}) {
  const socks5Proxy = createSocks5ProxyServer()

  socks5Proxy.on(
    EVENTS.REMOTE_CONNECTION_TIMEOUT_ERROR,
    ({originInfo, destinationInfo: {address, port}}) =>
      logger.error({
        action: 'remote-connection-timeout-error',
        address,
        port,
        originInfo,
      }),
  )

  socks5Proxy.on(EVENTS.ORIGIN_SOCKET_ERROR, ({err}) =>
    logger.warn({
      action: 'origin-socket-error',
      error: err,
    }),
  )

  socks5Proxy.on(
    EVENTS.REMOTE_SOCKET_ERROR,
    ({err, destination, args, originInfo, destinationInfo: {address, port}}) =>
      logger.warn({
        action: 'remote-socket-error',
        error: err,
        address,
        port,
      }),
  )

  socks5Proxy.on(EVENTS.ACCEPT_NEW_REQUEST, ({destinationInfo: {address, port}}) =>
    logger.info({
      action: 'socks5-accept-new-request',
      address,
      port,
    }),
  )

  socks5Proxy.on(EVENTS.CONNECTED_TO_REMOTE_ADDRESS, ({destinationInfo: {address, port}}) =>
    logger.info({
      action: 'connected-to-remote-address',
      address,
      port,
    }),
  )

  await socks5Proxy.listenAsync(port)

  const checkConnectionsLeakInterval = setInterval(
    () =>
      socks5Proxy.getConnections((error, count) => {
        if (error) return

        if (count < socks5Proxy.destinationSockets.length) {
          logger.warn({
            action: 'socks5-connections-leak',
            expectedSockets: count,
            actualSockets: socks5Proxy.destinationSockets.length,
          })
        }
      }),
    10000,
  )

  socks5Proxy.on('close', () => clearInterval(checkConnectionsLeakInterval))

  return socks5Proxy
}
