/* websocket-node */
const WebSocketServer = require('websocket').server
/* 定义全局变量 */
global.nsSocket = global.nsSocket || null
global.nsCoonPool = global.nsCoonPool || []

/**
 * 创建 socketServer 端
 * @param {[object]} _server 监听的服务接口对象
 */
const createServerSocket = (_server) => {
  let _nsSocket = new WebSocketServer({ httpServer: _server, autoAcceptConnections: false })
  /* 监听请求 */
  _nsSocket.on('request', function (_req) {
    /* 首先判断，socket连接是否合法 */
    if (!_connectIsAllowed(_req)) { _req.reject(); return }
    /* 创建一个连接对象 */
    let connection = _req.accept(null, _req.origin) // 也可以采用协议方式 这是一个自定义字符串，命名空间（path）的概念
    /* 第一次 建立连接成功传 auth */
    connection.sendBytes(Buffer.from(JSON.stringify({ auth: _req.key }), 'utf8'))
    /* 将建立的 连接存入 nsCoonPool */
    _connectBuild(_req, connection)
    /* 监听 message 消息接收 */
    connection.on('message', function (_msg) { _connectMessage(_msg) })
    /* 监听 close 连接关闭 */
    connection.on('close', function () { _connectClose() })
  })
  return _nsSocket
}

/**
 * 验证域名，socket是否可以跟服务端建立连接
 * @param {[object]} _req 请求对象
 */
const _connectIsAllowed = (_req) => { return true }
/**
 * 正式建立连接
 * @param {[object]} _req 请求对象
 * @param {[object]} connection 建立连接后对象
 */
const _connectBuild = (_req, connection) => {
  let _nsCoonPool = global.nsCoonPool
  /* 记录当前连接对象，并放入连接池 */
  _nsCoonPool.push({
    key: _req.key, // 标识连接的 唯一性
    backData: '', // 跟这个连接通信时，传来的数据存放
    createTime: new Date().getTime(), // socket创建时间
    conn: connection, // 当前已经 建立连接的对象
    cookies: JSON.stringify(_req.cookies), // 存放cookie值，每次建立时，只传递一次
    IPs: _req.remoteAddress, // 存放请求IP
    UA: _req.httpRequest.headers['user-agent'] // 存放请求浏览器UA
  })
}
/**
 * 处理接收到的请求数据
 * @param {[string]} _msg 传输的 数据
 */
const _connectMessage = (_msg) => {
  let _nsCoonPool = global.nsCoonPool
  let data = null
  if (_msg.type === 'utf8') {
    try {
      data = JSON.parse(_msg.utf8Data)
    } catch (e) {
      // connection.sendUTF(_msg.utf8Data)
      return '数据格式不正确1'
    }
  } else if (_msg.type === 'binary') {
    try {
      data = JSON.parse(Buffer.from(_msg.binaryData, 'utf8').toString())
    } catch (e) {
      return '数据格式不正确2'
    }
  }
  for (let i = 0; i < _nsCoonPool.length; i++) {
    if (_nsCoonPool[i].key === data.auth) {
      _nsCoonPool[i].backData = JSON.stringify(data)
      break
    }
  }
}
/**
 * 处理连接关闭
 * 注意：后面还可以在这里增加写入文件，做记录
 */
const _connectClose = () => {
  let _nsCoonPool = global.nsCoonPool
  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
    }
  }
}

/**
 * 发送数据
 * @param {[array]} connArr 针对那些 socket链接 进行处理
 * @param {[string]} action 需要执行的操作指令 字符串
 * @param {[string]} val 操作指令 对应的 字符串值
 */
const sendData = (connArr, action, val) => {
  let _nsCoonPool = global.nsCoonPool
  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) {
          let base64Str = Buffer.from(val).toString('base64')
          let jsonStr = JSON.stringify({ action: action, val: base64Str })
          _nsCoonPool[i].conn.sendBytes(Buffer.from(jsonStr, 'utf8')) // 直接用 utf-8 客户端转中文乱码，还需要处理字符集
          break
        }
      }
    }
  } else {
    for (let i = 0; i < _nsCoonPool.length; i++) {
      let base64Str = Buffer.from(val).toString('base64')
      let jsonStr = JSON.stringify({ action: action, val: base64Str })
      _nsCoonPool[i].conn.sendBytes(Buffer.from(jsonStr, 'utf8')) // 直接用 utf-8 客户端转中文乱码，还需要处理字符集
    }
  }
}

module.exports = {
  createServerSocket: createServerSocket,
  sendData: sendData
}
