import store from '@/store'
import { systemMessage } from './websocketMessage'

// 根据 请求头协议 转换对应 websocket 请求协议
const location = window.location.origin.replace('https://', 'wss://').replace('http://', 'ws://')
// 代理
const proxy = process.env.NODE_ENV === 'development' ? process.env.VUE_APP_PROXY : ''
// API 前缀
const prefix = process.env.VUE_APP_BASE_API
// WebSocket 地址
const url = process.env.VUE_APP_WS

// 最终请求的 WebSocket 路径
let wsUrl = ''

/**
 * 创建WebSocket
 * @author Matrix
 */
function loadWebsocket() {
  const user = store.getters.userInfo
  if (!user || !user.id) return
  wsUrl = location + proxy + prefix + url + user.id
  console.log('Websocket Url: ', wsUrl)
  initWebsocket()
  heartCheckFun()
}

let ws = null
let heartCheck = null
/**
 * 初始化 Websocket
 * @author Matrix
 */
function initWebsocket() {
  // 创建socket
  console.info(
    '%c****** 创建 WebSocket 连接 ******',
    'color: #409EFF;font-weight:bold;font-size:12px;font-family:"STXingkai","Microsoft YaHei","黑体","宋体",sans-serif;'
  )
  ws = new WebSocket(wsUrl)
  websocketReadyState()

  // 创建socket成功
  ws.onopen = function () {
    websocketReadyState()
    // 心跳检测重置
    heartCheck.reset().start()
  }

  // 接收到消息
  ws.onmessage = function (res) {
    // eslint-disable-next-line no-eval
    const data = eval('(' + res.data + ')') //解析对象console.log('websocket返回类型：' + data.cmd)
    // WebSocket 信息 在 websocketMessage.js 文件中单独封装，使结构清晰，便于管理。
    systemMessage(data)
    // 心跳检测重置
    heartCheck.reset().start()
  }

  // 关闭socket
  ws.onclose = function () {
    websocketReadyState()
    reconnect()
  }

  // 发生错误
  ws.onerror = function () {
    websocketReadyState()
    reconnect()
  }
}

const timeout = 20000
let timeoutObj = null
let serverTimeoutObj = null
/**
 * 心跳检测
 * @author Matrix
 */
function heartCheckFun() {
  // 创建一个定时器，心跳检测,每20s心跳一次
  heartCheck = {
    timeout,
    timeoutObj,
    serverTimeoutObj,
    reset: function () {
      clearTimeout(timeoutObj)
      clearTimeout(serverTimeoutObj)
      return this
    },
    start: function () {
      timeoutObj = setTimeout(function () {
        // 这里发送一个心跳，后端收到后，返回一个心跳消息
        try {
          ws.send('HeartBeat')
        } catch (err) {
          console.warn('send failed (' + err.code + ')')
        }
        serverTimeoutObj = setTimeout(function () {
          // 如果超过一定时间还没重置，说明后端主动断开了
          ws.close()
        }, timeout)
      }, timeout)
    }
  }
}

// 避免重复连接
let lockReconnect = false
/**
 * 重连
 * @author Matrix
 */
function reconnect() {
  if (lockReconnect) return
  lockReconnect = true
  // 没连接上会一直重连，设置延迟避免请求过多
  setTimeout(function () {
    initWebsocket()
    lockReconnect = false
  }, 5000)
}

/**
 * websocket状态
 * @author Matrix
 */
function websocketReadyState() {
  switch (ws.readyState) {
    case WebSocket.CONNECTING:
      console.info(
        '%c****** WebSocket 正在连接... ******',
        'color: #E6A23C;font-weight:bold;font-size:12px;font-family:"STXingkai","Microsoft YaHei","黑体","宋体",sans-serif;'
      )
      break
    case WebSocket.OPEN:
      console.info(
        '%c****** WebSocket 连接成功，可以通信！******',
        'color: #67C23A;font-weight:bold;font-size:12px;font-family:"STXingkai","Microsoft YaHei","黑体","宋体",sans-serif;'
      )
      break
    case WebSocket.CLOSING:
      console.info(
        '%c****** WebSocket 连接正在关闭！******',
        'color: #F56C6C;font-weight:bold;font-size:12px;font-family:"STXingkai","Microsoft YaHei","黑体","宋体",sans-serif;'
      )
      break
    case WebSocket.CLOSED:
      console.info(
        '%c****** WebSocket 连接已经关闭，或者打开连接失败！******',
        'color: #606266;font-weight:bold;font-size:12px;font-family:"STXingkai","Microsoft YaHei","黑体","宋体",sans-serif;'
      )
      break
    default:
      break
  }
}

export { loadWebsocket }
