<template>
  <div class="w-48% float-left border-solid border-bluegray border-2">
    <el-scrollbar ref="scrollbarRef" style="height: 34rem;" class="mb-10 " always>
      <div ref="innerRef" class="bg-black">
        <p v-for="item in items" :key="item" class="scrollbar-demo-item text-sm">
        <div>{{ JSON.parse(item)?.ts }}</div>
        {{ item }}
        </p>
      </div>
    </el-scrollbar>

    <div>
      <el-button  type="primary" round class="ml-4 mb-2" @click="showCmdDialog">发送指令</el-button>
    </div>
  </div>

  <div class="w-50% float-right border-solid border-bluegray border-2">
    <el-tabs v-model="activeName" class="px-5">
      <el-tab-pane label="设备" name="device">
        <el-scrollbar style="height: 30rem;" class="mb-10" always>
          <device-performance-table 
            v-for="param in deviceTableParams" 
            class="mt-5" 
            :dev-name="param.devName"
            :protocol-name="param.protocolName" 
            :group-name="param.key" 
            :key="param.key"
            :type="activeName==='device'?'1': '2'"
            @delete-table="deleteDeviceInfo(param)" />
        </el-scrollbar>
        <el-button class="mb-2"  type="primary" round @click="dialogVisible = true">添加监控设备表</el-button>
      </el-tab-pane>
      <el-tab-pane label="虚拟设备" name="simulateDevice">
        <el-scrollbar style="height: 30rem;" class="mb-10" always>
          <device-performance-table 
            v-for="param in simulateDeviceTableParams" 
            class="mt-5" 
            :dev-name="param.devName"
            :protocol-name="param.protocolName" 
            :group-name="param.key" 
            :key="param.key"
            :type="activeName==='device'?'1': '2'"
            @delete-table="deleteDeviceInfo(param)" />
        </el-scrollbar>
        <el-button class="mb-2"  type="primary" round @click="dialogVisible = true">添加监控设备表</el-button>
      </el-tab-pane>
    </el-tabs>
  </div>

  <el-dialog class="w-150" v-model="dialogVisible" title="Select device">
    <el-select class="w-100" v-model="selectedDeviceName">
      <el-option v-for="deviceInfo in deviceInfos" :key="deviceInfo.dev_name" :label="deviceInfo.dev_name"
        :value="deviceInfo.dev_name" />
    </el-select>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="addDeviceTable">
          确定
        </el-button>
      </span>
    </template>
  </el-dialog>

  <el-dialog v-model="dialogCmdVisible" class="w-150" title="发送指令" draggable>
    <el-form :model="formData" label-width="120px">
      <el-form-item label="设备名称">
        <el-select v-model="formData.deviceName" w-100 @change="showCmds">
          <el-option 
            v-for="deviceName in deviceNamesOptions" 
            :label="deviceName.label" 
            :value="deviceName.value" />
        </el-select>
      </el-form-item>
      <el-form-item label="命令">
        <el-select v-model="formData.cmdName" w-100 @change="showFields">
          <el-option
            v-for="cmdName in cmdNamesOptions"
            :label="cmdName.label"
            :value="cmdName.value" />
        </el-select>
      </el-form-item>
      <el-form-item v-for="field in formData.fields" :label="field.fieldname">
        <el-input v-model="field.value" />
      </el-form-item> 
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogCmdVisible = false">取消</el-button>
        <el-button type="primary" @click="sendCmd">
          确定
        </el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, onMounted, watch, onBeforeUnmount, reactive } from 'vue';
import { ElScrollbar, ElButton, ElSelect, ElOption, ElMessage } from 'element-plus';
import DevicePerformanceTable from '@/components/home/DevicePerformanceTabel'
import axios from 'axios';


const innerRef = ref<HTMLDivElement>();
const scrollbarRef = ref<InstanceType<typeof ElScrollbar>>();
const items = ref<string[]>([]);
const flag = ref<boolean>(false);
let chatSocket: WebSocket | null = null;

watch(flag, () => {
  setTimeout(() => {
    scrollbarRef.value!.setScrollTop(innerRef.value!.offsetHeight);
  }, 50);
});

onMounted(() => {
  chatSocket = new WebSocket(
    'ws://'
    + window.location.host
    + '/ws/chat/mqtt/'
  );

  chatSocket.onmessage = (e) => {
    // console.log(e);
    // console.log(e.data)
    // // 接收到的是字节流数据（ArrayBuffer）
    // const byteArray = new Uint8Array(e.data);
    // // 将字节流转换为字符串或其他格式进行处理
    // const message = byteArray.toString();
    // items.value.push(JSON.stringify(e.data));
    let message = decodeURIComponent(e.data)
    // TODO 处理数据，看是否有是被检测的设备
    items.value.push(message);
    flag.value = !flag.value
  };

  axios.get('/api/xpro_all_devinfo/')
    .then((res) => {
      deviceInfos.value = res.data
    })
    .catch((err) => {
      console.log(err);
    })
})

onBeforeUnmount(() => {
  chatSocket?.close();
})

// 添加设备监控操作
const deviceInfos = ref<any[]>([]);
const selectedDeviceName = ref<string>('')
const dialogVisible = ref<boolean>(false);
type MonitorType = {
  key: string
  protocolName: string
  devName: string
}

// tab
// 维护两个列表，通过判断当前在哪个标签页就对谁添加
// 删除同理
const activeName = ref<string>('device')
const deviceTableParams = ref<MonitorType[]>([]);
const simulateDeviceTableParams = ref<MonitorType[]>([]);
const addDeviceTable = () => {
  if (deviceInfos.value.length === 0) {
    ElMessage.warning('input invalid');
    return;
  }

  for (let deviceInfo of deviceInfos.value) {
    if (deviceInfo.dev_name === selectedDeviceName.value) {
      if ((deviceInfo.comunitate_mode as string).toUpperCase().includes('TCP')) {
        if (activeName.value === 'device') {
          deviceTableParams.value.push({
            key: (deviceInfo.tcp_port).toString(),
            protocolName: deviceInfo.protocol_name,
            devName: deviceInfo.dev_name
          });
        }
        else {
          simulateDeviceTableParams.value.push({
            key: (deviceInfo.tcp_port).toString(),
            protocolName: deviceInfo.protocol_name,
            devName: deviceInfo.dev_name
          })
        }
      }
      else {
        if (activeName.value === 'device') {
          deviceTableParams.value.push({
            key: (deviceInfo.udp_port_src).toString(),
            protocolName: deviceInfo.protocol_name,
            devName: deviceInfo.dev_name
          });
        }
        else {
          simulateDeviceTableParams.value.push({
            key: (deviceInfo.udp_port_src).toString(),
            protocolName: deviceInfo.protocol_name,
            devName: deviceInfo.dev_name
          })
        }
      }
    }
  }

  dialogVisible.value = false
  ElMessage.success(`add ${selectedDeviceName.value} successfully!`);
}

const deleteDeviceInfo = (param: MonitorType) => {
  if (activeName.value === 'device') {
    deviceTableParams.value.splice(deviceTableParams.value.indexOf(param), 1);
  }
  else {
    simulateDeviceTableParams.value.splice(simulateDeviceTableParams.value.indexOf(param), 1);
  }
}

// send Cmd

type FieldDataType = {
  fieldname: string
  value: string
}
type FromDataType = {
  deviceName: string
  cmdName: string
  fields: FieldDataType[]
}
const formData = reactive<FromDataType>({
  deviceName: '',
  cmdName: '',
  fields: []
})
const dialogCmdVisible = ref<boolean>(false);
type OptionType = {
  label: string
  value: string
}
const deviceNamesOptions = ref<OptionType[]>([])
const deviceNameMap = new Map<string, any>()
const showCmdDialog = () => {
  dialogCmdVisible.value = true

  // 如果 options 中没有内容的话，将信息存到 options 中
  if (deviceNamesOptions.value.length === 0) {
    for (let deviceInfo of deviceInfos.value) {
      deviceNamesOptions.value.push({
        label: deviceInfo.dev_name,
        value: deviceInfo.dev_name
      })
    }
  }

  // 如果 map 中没有内容的话，将信息存到一个 map 中方便查找
  if (deviceNameMap.size === 0) {
    for (let deviceInfo of deviceInfos.value) {
      deviceNameMap.set(deviceInfo.dev_name, deviceInfo)
    }
  }
}

const cmdNamesOptions = ref<OptionType[]>([])
const showCmds = () => {
  cmdNamesOptions.value.splice(0, cmdNamesOptions.value.length);
  axios.get('/api/mqtt/protocol/' + deviceNameMap.get(formData.deviceName).protocol_name + '/')
  .then((res) => {
    for (let item of res.data) {
      cmdNamesOptions.value.push({
        label: item,
        value: item
      })
    }
  })
  .catch((err) => {
    console.log(err);
  })
}

const filterFields = ["CMDS", "END", "Comma"]
const showFields = () => {
  axios.get('/api/mqtt/cmd/' + formData.cmdName + '/')
  .then((res) => {
    formData.fields = res.data.filter((item: FieldDataType) => 
      !filterFields.includes(item.fieldname)
    )
  })
  .catch((err) => {
    console.log(err);
  })
}

const sendCmd = () => {
  dialogCmdVisible.value = false

  // 发送命令
  const obj = deviceNameMap.get(formData.deviceName)
  axios.post('/api/mqtt/publish/',
  {
    station_id: obj.sta_id,
    device_id: obj.dev_id,
    cmd_name: formData.cmdName,
    fields: formData.fields
  })
  .catch((err) => {
    console.log(err);
  })

  // 展示到聊天框
  let cmdText = `设备 ${formData.deviceName} 发送命令 ${formData.cmdName}`
  if (chatSocket === null) {
    console.error('chatSocket is null');
    return;
  }  
  chatSocket.send(JSON.stringify({
    'message': cmdText
  }));
}

</script>

<style scoped>
.scrollbar-demo-item {
  display: flex;
  /* align-items: center; */
  /* justify-content: center; */
  height: auto;
  padding: 8px;
  text-align: left;
  background: #f4f4f4;
  color: #4d4c4c;
}
</style>
