<template>
  <div class="app-container">
    <!--工具栏-->
    <div class="head-container">
      <div v-if="crud.props.searchToggle">
        <!-- 搜索 -->
        <el-input
          v-model="query.tag"
          clearable
          size="small"
          placeholder="请输入标签名"
          style="width: 170px"
          class="filter-item"
          @keyup.enter.native="crud.toQuery"
        />
        <el-input
          v-model="query.description"
          clearable
          size="small"
          placeholder="请输入标签描述"
          style="width: 170px"
          class="filter-item"
          @keyup.enter.native="crud.toQuery"
        />
        <el-select
          v-model="query.connId"
          clearable
          size="small"
          placeholder="所属连接"
          class="filter-item"
          style="width: 120px"
          @change="handleConnChange"
        >
          <el-option
            v-for="item in optionsObj.Conn"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
        <el-select
          v-model="query.deviceId"
          clearable
          size="small"
          placeholder="所属设备"
          class="filter-item"
          style="width: 120px"
          @change="crud.toQuery"
        >
          <el-option
            v-for="item in deviceOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
        <el-select
          v-model="query.dataType"
          clearable
          size="small"
          placeholder="数据类型"
          class="filter-item"
          style="width: 120px"
          @change="crud.toQuery"
        >
          <el-option
            v-for="item in optionsObj.DataType"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
        <rrOperation />
      </div>
      <crudOperation :permission="permission" />
    </div>
    <!--表格渲染-->
    <el-table ref="table" v-loading="crud.loading" :data="crud.data">
      <el-table-column
        v-for="item in dataManagerTableOptions"
        :key="item.prop"
        :label="item.label"
        :prop="item.prop"
        :width="item.width"
        :align="item.align"
        :fixed="item.fixed"
        :sortable="item.sortable"
        show-overflow-tooltip
      >
      </el-table-column>
      <el-table-column label="当前值" width="100px" align="center">
        <template slot-scope="scope">
          <span>{{ currData[scope.row.tag] ? currData[scope.row.tag].Value : '' }}</span>
        </template>
      </el-table-column>
      <el-table-column label="当前状态" width="100px" align="center">
        <template slot-scope="scope">
          <span>{{ currData[scope.row.tag] ? currData[scope.row.tag].Status ? '正常' : '异常' : '' }}</span>
        </template>
      </el-table-column>
      <el-table-column label="最后更新时间" width="160px" align="center">
        <template slot-scope="scope">
          <span>{{ currData[scope.row.tag] ? currData[scope.row.tag].Time : '' }}</span>
        </template>
      </el-table-column>
      <el-table-column label="异常信息" align="center">
        <template slot-scope="scope">
          <span>{{ currData[scope.row.tag] ? currData[scope.row.tag].ErrorMessage : '' }}</span>
        </template>
      </el-table-column>
    </el-table>
    <pagination />
  </div>
</template>

<script>
import Vue from 'vue'
import permission from '@/directive/permission'
import crudDataManager from '@/api/dataComm/dataManager'
import CRUD, { presenter, header, form, crud } from '@crud/crud'
// import { crudOperation, rrOperation, udOperation, pagination } from '@crud'
import crudComps from '@crud'
import { getOptions } from '@/api/dataComm/options'
import * as mqtt from 'mqtt'
import Dayjs from 'dayjs'
import lodash from 'lodash'
import { getMQTTCilentId } from '@/utils/mqtt'

// 表头配置
import { dataManagerTableOptions } from '../tableConfig'

const defaultForm = {}

export default {
  name: 'RealTimeData',
  directives: { permission },
  mixins: [presenter(), header(), form(defaultForm), crud()],
  components: { ...crudComps },
  cruds() {
    return CRUD({
      title: '实时数据',
      url: 'dataCommunicationManage/generalTag/getList',
      params: { enable: true },
      crudMethod: { ...crudDataManager },
      optShow: {
        add: false,
        edit: false,
        del: false,
        reset: false,
        import: false,
        export: false,
      },
    })
  },
  data() {
    return {
      dataManagerTableOptions,
      rules: {
        dataManagerName: [
          {
            required: true,
            message: '请输入名称',
            trigger: 'blur',
          },
        ],
      },
      permission: {
        add: ['admin', 'datacommunicationmanage:generaltag:add'],
        edit: ['admin', 'datacommunicationmanage:generaltag:edit'],
        del: ['admin', 'datacommunicationmanage:generaltag:del'],
      },
      optionsObj: {
        DataType: [],
        Conn: [],
      },
      mqttClient: null,
      topicArray: [],
      currData: {},
      deviceOptions: [],
    }
  },
  computed: {
    VUE_APP_BASE_API() {
      return process.env.VUE_APP_BASE_API
    },
    VUE_APP_BASE_WS() {
      return 'ws://' + window.location.host + process.env.VUE_APP_BASE_API
    },
  },
  created() {
    this.getOptions()
    this.startMQTT()
  },
  beforeDestroy() {
    this.mqttClient.end()
  },
  mounted() {},
  methods: {
    [CRUD.HOOK.afterRefresh]() {
      this.refreshSubscribe()
    },
    //开始MQTT接收
    startMQTT() {
      // 连接选项
      const options = {
        clean: true, // true: 清除会话, false: 保留会话
        keepalive: 60,
        connectTimeout: 4000, // 超时时间
        // 认证信息
        clientId: getMQTTCilentId("realtimedata"),
        username: 'client',
        password: '19c9547ad2029be96774fce5f1b9f099',
      }
      const connectUrl = this.VUE_APP_BASE_WS + '/MQTTOverWebSocket'
      //console.log(connectUrl)
      this.mqttClient = mqtt.connect(connectUrl, options)

      let _this = this
      this.mqttClient.on('connect', function () {
        //订阅主题
        console.log('实时数据MQTT正在连接')
        //if (_this.topicArray.length > 0) {
          //_this.mqttClient.subscribe(_this.topicArray)
          //console.log('订阅1', this.topicArray)
        //}
      })
      this.mqttClient.on('message', (topic, message) => {
        if (topic == 'Online') {
          console.log('实时数据MQTT收到消息：', topic, message.toString())
        } else if (topic.startsWith('DataCommunication/TagData/')) {
          let data = JSON.parse(message.toString())
          //console.log(JSON.parse(message.toString()))
          Vue.set(this.currData, data.Tag, data)
        }
      })
    },
    refreshSubscribe() {
      //console.log('refreshSubscribe')
      this.currData = {}
      if (this.mqttClient && this.mqttClient.connected) {
        //console.log(this.mqttClient)
        let newTopicArray = this.crud.data.map((a) => 'DataCommunication/TagData/' + a.tag)
        let unsubscribeTopicArray = lodash.difference(this.topicArray, newTopicArray)
        if (unsubscribeTopicArray.length > 0) {
          //console.log('解除订阅', unsubscribeTopicArray)
          this.mqttClient.unsubscribe(unsubscribeTopicArray)
        }
        let subscribeTopicArray = lodash.difference(newTopicArray, this.topicArray)
        if (subscribeTopicArray.length > 0) {
          //console.log('订阅', subscribeTopicArray)
          this.mqttClient.subscribe(subscribeTopicArray)
        }
        this.topicArray = newTopicArray
      } else {
        setTimeout(() => {
          //console.log('setTimeout refreshSubscribe')
          this.refreshSubscribe()
        }, 1000);
      }
    },
    handleConnChange(value){
      getOptions('Device', { id: value }).then(res => {
        if (res.code === 20000) {
          this.query.deviceId = null
          this.deviceOptions = res.data.content
          this.crud.toQuery()
        }
      })
    },
    getOptions() {
      Object.keys(this.optionsObj).forEach(async (key) => {
        try {
          let res = await getOptions(key)
          if (res.code === 20000) this.optionsObj[key] = res.data.content
        } catch (error) {
          console.log(error)
        }
      })
    },
  },
}
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
::v-deep .vue-treeselect__control,
::v-deep .vue-treeselect__placeholder,
::v-deep .vue-treeselect__single-value {
  height: 30px;
  line-height: 30px;
}
</style>
<style rel="stylesheet/scss" lang="scss" scoped>
::v-deep .el-input-number .el-input__inner {
  text-align: left;
}
</style>
