# recognizer/websocket/networkWSInterface.js

    import { recognizerLogger as logger } from '../../configuration/LoggerConfig'
    import * as RecognizerContext from '../../model/RecognizerContext'

    function infinitePing (websocket) {
      const websocketRef = websocket
      websocketRef.pingLostCount++
      if (websocketRef.pingLostCount > websocketRef.maxPingLost) {
        websocket.close(1000, 'PING_LOST')
      } else if (websocketRef.readyState <= 1) {
        setTimeout(() => {
          if (websocketRef.readyState <= 1) {
            websocketRef.send(JSON.stringify({ type: 'ping' }))
            infinitePing(websocketRef)
          }
        }, websocketRef.pingDelay)
      }
    }

    /**
     * Attach all socket attributes helping managing server connexion
     * @param {WebSocket} websocket Current WebSocket
     * @param {RecognizerContext} recognizerContext
     */
    function addWebsocketAttributes (websocket, recognizerContext) {
      const websocketConfiguration = recognizerContext.editor.configuration.recognitionParams.server.websocket
      const socket = websocket
      socket.start = new Date()
      socket.autoReconnect = websocketConfiguration.autoReconnect
      socket.maxRetryCount = websocketConfiguration.maxRetryCount
      socket.pingEnabled = websocketConfiguration.pingEnabled
      socket.pingDelay = websocketConfiguration.pingDelay
      socket.maxPingLost = websocketConfiguration.maxPingLostCount
      socket.pingLostCount = 0
      socket.recognizerContext = recognizerContext
    }

    /**
     * @param {RecognizerContext} recognizerContext Recognizer context
     * @return {WebSocket} Opened WebSocket
     */
    export function openWebSocket (recognizerContext) {
      let socket
      try {
        // eslint-disable-next-line no-undef
        socket = new WebSocket(recognizerContext.url)
      } catch (error) {
        logger.error('Unable to open websocket, Check the host and your connectivity')
      }
      addWebsocketAttributes(socket, recognizerContext)
      if (socket.pingEnabled) {
        infinitePing(socket)
      }

      socket.onopen = (e) => {
        logger.trace('onOpen')
        recognizerContext.websocketCallback(e)
      }

      socket.onclose = (e) => {
        logger.trace('onClose', new Date() - socket.start)
        recognizerContext.websocketCallback(e)
      }

      socket.onerror = (e) => {
        logger.trace('onError')
        recognizerContext.websocketCallback(e)
      }

      socket.onmessage = (e) => {
        logger.trace('onMessage')
        socket.pingLostCount = 0
        const parsedMessage = JSON.parse(e.data)
        if (parsedMessage.type !== 'pong') {
          const callBackParam = {
            type: e.type,
            data: JSON.parse(e.data)
          }
          recognizerContext.websocketCallback(callBackParam)
        }
      }

      return socket
    }

    /**
     * Send data message
     * @param {RecognizerContext} recognizerContext Current recognizer context
     * @param {Object} message Data message
     */
    export function send (recognizerContext, message) {
      const recognizerContextRef = recognizerContext
      recognizerContextRef.idle = false

      const websocket = recognizerContextRef.websocket
      if (websocket.readyState === 1) {
        websocket.send(JSON.stringify(message))
        logger.debug(`${message.type} message sent`, message)
      } else {
        throw RecognizerContext.LOST_CONNEXION_MESSAGE
      }
    }

    /**
     * Close the websocket
     * @param {RecognizerContext} recognizerContext Current recognizer context
     * @param {Number} code Exit code
     * @param {String} reason Exit reason
     */
    export function close (recognizerContext, code, reason) {
      const websocket = recognizerContext.websocket
      if (websocket && websocket.readyState < 2) {
        websocket.close(code, reason)
      }
    }