/* websocket-node */
const WebSocketServer = require('websocket').server
let nsSocket = null
let nsCoonPool = []

const sendMsg = (req, res) => {
  /* 创建一个 websocket-server Node端 */
  if (!nsSocket) nsSocket = createNodeServerSocket(global.SocketServer)

  /* 接口执行操作 */
  if (nsSocket) {
    if (req.body.sendMsg === 'send') {
      sendDataFromServerSocket(req.body.arr && req.body.arr.split(','), req.body.action, req.body.val)
      res.status(200).send({ msg: '已向客户端发送消息' })
    } else {
      let _conArr = []
      for (let i = 0; i < nsCoonPool.length; i++) {
        _conArr.push({ auth: nsCoonPool[i].key })
      }
      res.status(200).send({ linkCount: nsCoonPool.length, connections: _conArr })
    }
  } else {
    res.status(200).send({ msg: 'ServerSocket not publish' })
  }
}

const createNodeServerSocket = (_server) => {
  let _nsSocket = new WebSocketServer({
    httpServer: _server, // 必填，依托于服务
    autoAcceptConnections: false // 不用自动建立连接，建立过程中，通过origin等进行授权认证，是否为合法websocket客户端
  })
  /* 监听请求 */
  _nsSocket.on('request', function (_req) {
    /* 首先判断，socket连接是否合法 */
    if (!_isAllowed(_req)) { _req.reject(); return }
    /* 创建一个连接对象 */
    let connection = _req.accept(null, _req.origin) // 也可以采用协议方式 这是一个自定义字符串，命名空间（path）的概念
    connection.sendBytes(Buffer.from(JSON.stringify({ auth: _req.key }))) // 发送auth，以后发送数据都带上否则拒绝处理
    /* 记录当前连接对象，并放入连接池 */
    nsCoonPool.push({
      key: _req.key, // 标识连接的 唯一性
      conn: connection // 当前已经 建立连接的对象
    })
    /* 监听 message 消息接收 */
    connection.on('message', function (_msg) { _dealData(_msg) })
    /* 监听 close 连接关闭 */
    connection.on('close', function () {
      for (let i = 0; i < nsCoonPool.length; i++) {
        let _item = nsCoonPool[i]
        if (!_item.conn.connected && _item.conn.state === 'closed') {
          nsCoonPool.splice(i, 1)
          delete _item.conn
        }
      }
    })
  })
  /* 验证域名，socket可连接 */
  function _isAllowed (_req) {
    // 检测 _req.origin、_req.host、_req.remoteAddress、_req.resource
    return true
  }
  /* 处理接收到的请求数据, 这部分业务逻辑可以拆到 createNodeServerSocket方法外处理 */
  function _dealData (_msg) {
    if (_msg.type === 'utf8') {
      /* String转JSON，直接处理 */
      // connection.sendUTF(_msg.utf8Data)
    } else if (_msg.type === 'binary') {
      /* 数据类型转换JSON，再处理 */
      let data = JSON.parse(Buffer.from(_msg.binaryData).toString('utf8'))
      if (data.action === 'sendAuth') {
        /* conn验证，发送消息的是连接池中的哪个conn */
        let i = 0
        for (; i < nsCoonPool.length; i++) {
          if (nsCoonPool[i].key === data.auth && data.info) {
            let _arr = Buffer.from(data.info, 'base64').toString().split(':')
            nsCoonPool[i].name = _arr[0]
            nsCoonPool[i].iphone = _arr[1]
            nsCoonPool[i].email = _arr[2]
            nsCoonPool[i].id = _arr[3]
            nsCoonPool[i].auth_key = _arr[4]
            break
          }
        }
      }
    }
  }
  return _nsSocket
}

const sendDataFromServerSocket = (connArr, action, val) => {
  if (connArr.length) {
    for (let j = 0; j < connArr.length; j++) {
      for (let i = 0; i < nsCoonPool.length; i++) {
        if (connArr[j] === nsCoonPool[i].key) {
          nsCoonPool[i].conn.sendBytes(Buffer.from(JSON.stringify({ action: action, val: Buffer.from(val).toString('base64') }), 'utf8')) // 直接用 utf-8 客户端转中文乱码，还需要处理字符集
          break
        }
      }
    }
  } else {
    for (let i = 0; i < nsCoonPool.length; i++) {
      nsCoonPool[i].conn.sendBytes(Buffer.from(JSON.stringify({ action: action, val: Buffer.from(val).toString('base64') }), 'utf8')) // 直接用 utf-8 客户端转中文乱码，还需要处理字符集
    }
  }
}

module.exports = {
  sendMsg: sendMsg
}
