import mqtt from 'mqtt'
import { findCurrentMqtt } from '@/api/MqttConfig'
import { Notification } from 'element-ui'
import { findClientWarnRecord } from '@/api/WarnRecord'
import moment from 'moment'
import Vue from 'vue'
import { v4 as uuidv4 } from 'uuid'

const WARN_DURING = 1000 * 60 * 0.5
const WARN_TIMEOUT = 1000 * 60 * 1

const queue = {
  state: {
    client: null,
    realtimeData: null,
    realtimeDataMap: {},
    lastTime: null,
    warnRecordData: [],
    warnSystem: {
      status: false,
      currentWarnRecord: {},
    },

    alarmActiveStatus: {},
  },

  mutations: {
    SET_CLIENT: (state, payload) => {
      state.client = payload
    },
    SET_REALTIME_DATA: (state, payload) => {
      state.realtimeData = payload
      for (const e of payload) {
        state.realtimeDataMap[e.tag] = e.value
      }
      state.lastTime = moment(Number(payload[0].timestamp)).format('HH:mm:ss')
    },
    SET_WARN_RECORD: (state, payload) => {
      if (state.warnRecordData.length >= 10) {
        state.warnRecordData.pop()
      }
      state.warnRecordData.unshift(payload)
      state.warnSystem.currentWarnRecord = payload
      state.warnSystem.status = true
      const timeout = setTimeout(() => {
        state.warnSystem.currentWarnRecord = {}
        state.warnSystem.status = false
        clearTimeout(timeout)
      }, 3000)
    },
    SET_WARN_RECORD_ASC: (state, payload) => {
      if (payload && payload.length > 0) {
        payload.forEach(e => {
          state.warnRecordData.push(e)
        })
      } else {
        state.warnRecordData = []
      }

    },
    START_ALARM: (state, payload) => {
      if (state.alarmActiveStatus[payload.tagId] && state.alarmActiveStatus[payload.tagId].isEnabled) {
        Vue.prototype.playAudio()
        Notification.error({
          title: payload.desc,
          message: '当前值: ' + payload.currentValue,
          duration: 10000,
          // dangerouslyUseHTMLString: true,
          // message: '<strong>这是 <i>HTML</i> 片段</strong>'
        })
      }
    },
    STOP_ALARM: (state, payload) => {
      state.audio.pause()
      state.audio.currentTime = 0
    },
    SET_ALARM_ACTIVE_STATUS: (state, payload) => {
      // 初始化数据
      if (!state.alarmActiveStatus[payload.tagId]) {
        state.alarmActiveStatus[payload.tagId] = {
          isEnabled: true,
          records: [],
          // 定时器, 延时设置报警状态设置isEnabled = true
          timer: null,
        }
      }
      // 报警记录(连续不间断的数据, 并且持续时间在2分钟以内)
      const arr = state.alarmActiveStatus[payload.tagId].records
      // 报警状态(是否启用)
      const isEnabled = state.alarmActiveStatus[payload.tagId].isEnabled

      // 报警启用状态
      if (isEnabled) {
        // 判断报警记录是否为空, 如果为空说明不是连续报警,直接将报警记录保存到List
        if (arr.length === 0) {
          state.alarmActiveStatus[payload.tagId].records.push(payload)
        } else {
          // 如果报警记录不为空, 获取最后一次报警记录, 获取时间差, 如果时间差大于
          // 报讯记录中的最后一条记录
          const lastRecord = arr.at(-1)
          // 当前报警记录与最后一条报警记录的时间差
          const lastTimeDiff = (Number(payload.warnTime) - Number(lastRecord.warnTime))
          // 如果时间差大于8秒, 认为不是连续报警, 清空以前的记录
          if (lastTimeDiff > 8000) {
            state.alarmActiveStatus[payload.tagId].records = []
          } else {
            // 如果时间差小于等于8秒, 获取第一条报警记录, 计算时间差
            const firstRecord = arr.at(0)
            const firstTimeDiff = (Number(payload.warnTime) - Number(firstRecord.warnTime))
            // 如果时间差大于报警最大持续时间, 关闭报警状态, 设置延时任务, 5分钟后开启报警状态
            if (firstTimeDiff > WARN_DURING) {
              // 设置报警为不可用状态
              setAlarmDisabled(state, payload)
            } else {
              // 将报警记录保存到records
              state.alarmActiveStatus[payload.tagId].records.push(payload)
            }
          }
        }
      }
      // 未启用状态不进行操作
    },
    CLEAR_WARN_DATA: (state, payload) => {
      state.warnRecordData = []
    }
  },

  actions: {
    initMqtt({ commit }) {
      findCurrentMqtt().then(res => {
        if (res && res.code === '200') {
          const client = conn(res.data)
          client.on('connect', () => onConnect(res.data, client))
          client.on('message', (topic, message) => receiveMessages(topic, message, commit, res.data))
          client.on('end', () => onEnd())
          client.on('offline', () => onOffline(client))
          //如果连接错误，打印错误
          client.on('error', err => onError(err, client))
          commit('SET_CLIENT', client)
        }
      })
    },
    initWarnRecordData({ commit }) {
      findClientWarnRecord().then(res => {
        if (res && res.code === '200') {
          commit('SET_WARN_RECORD_ASC', res.data)
        }
      })
    },
  }
}

const conn = mqttConfig => {
  const options = {
    //mqtt客户端的id
    clientId: mqttConfig.receiveClientId + '_' + uuidv4(),
    host: mqttConfig.host.substring(6),
    port: mqttConfig.port,
    protocol: 'tcp',
    connectTimeout: mqttConfig.connectionTimeout * 1000,
    username: mqttConfig.username,
    password: mqttConfig.password,
    clean: true
  }
  return mqtt.connect(options)
}

const onConnect = (mqttConfig, client) => {
  Notification({
    title: '成功',
    message: 'MQTT连接成功',
    duration: 2000,
    type: 'success'
  })
  console.log('连接成功....')
  client.subscribe(mqttConfig.realtimeDataTopic, { qos: 1 }, error => {
    if (!error) {
      console.log('主题: ' + mqttConfig.realtimeDataTopic + ' 订阅成功')
    } else {
      console.error('主题: ' + mqttConfig.realtimeDataTopic + ' 订阅失败')
    }
  })
  client.subscribe(mqttConfig.warnRecordTopic, { qos: 1 }, error => {
    if (!error) {
      console.log('主题: ' + mqttConfig.warnRecordTopic + ' 订阅成功')
    } else {
      console.error('主题: ' + mqttConfig.warnRecordTopic + ' 订阅失败')
    }
  })
}

const onEnd = () => {
  console.warn('MQTT断开连接!')
}

const onOffline = (client) => {
  console.error('MQTT OFFLINE !')
  const timer = setTimeout(() => {
    client.reconnect()
    clearTimeout(timer)
  }, 2000)
  /*Notification({
    title: '错误',
    message: 'MQTT连接失败',
    duration: 2000,
    type: 'error'
  })*/
}

const onError = (err, client) => {
  console.error('err=>', err)
  client.end()
  const timer = setTimeout(() => {
    client.reconnect()
    clearTimeout(timer)
  }, 2000)
  Notification({
    title: '错误',
    message: 'MQTT连接失败',
    duration: 2000,
    type: 'error'
  })
}

const receiveMessages = (topic, message, commit, mqttConfig) => {
  const mqttMessage = JSON.parse(message.toString())
  // console.log('收到来自', topic, '的消息---->>', message.toString())
  // console.log('收到来自', topic, '的消息---->>', JSON.parse(message.toString()))
  if (topic === mqttConfig.realtimeDataTopic) {
    commit('SET_REALTIME_DATA', mqttMessage)
    // console.log('收到来自', topic, '的消息---->>', message.toString())
  } else if (topic === mqttConfig.warnRecordTopic) {
    commit('SET_WARN_RECORD', mqttMessage)
    // console.log('收到来自', topic, '的消息---->>', message.toString())
    // TODO 将两个commit取消注释, 下面内容注释掉
    const msg = JSON.parse(message.toString())
    Notification.error({
      title: msg.desc,
      message: '当前值: ' + msg.currentValue,
      duration: 10000,
      // dangerouslyUseHTMLString: true,
      // message: '<strong>这是 <i>HTML</i> 片段</strong>'
    })
    Vue.prototype.playAudio()

    // commit('SET_ALARM_ACTIVE_STATUS', mqttMessage)
    // commit('START_ALARM', mqttMessage)
  }
}

// 关闭告警
const setAlarmDisabled = (state, warnMessage) => {
  // isEnabled = false
  // records = []
  // 添加延时器 5分钟后 设置isEnabled = true
  state.alarmActiveStatus[warnMessage.tagId].records = []
  state.alarmActiveStatus[warnMessage.tagId].isEnabled = false
  state.alarmActiveStatus[warnMessage.tagId].timer = setTimeout(() => {
    state.alarmActiveStatus[warnMessage.tagId].records = []
    state.alarmActiveStatus[warnMessage.tagId].isEnabled = true
    clearTimeout(state.alarmActiveStatus[warnMessage.tagId].timer)
    state.alarmActiveStatus[warnMessage.tagId].timer = null
  }, WARN_TIMEOUT)
  Vue.prototype.stopAudio()
}

export default queue
