<template>
  <a-card>
    <a-row>
      <a-col>
        <a-space>
          <a-select
          allowClear
            placeholder="请选择产品"
            v-model:value="state.modelId"
            style="width: 170px"
          >
            <a-select-option
              v-for="model in state.modelList"
              :key="model.id"
              :value="model.id"
            >
              {{model.modelLabel}}
            </a-select-option>
          </a-select>
          <a-button @click="exportDomToImage" >导出</a-button>
        </a-space>
      </a-col>
    </a-row>

    <a-spin style="width: 1000px;" :spinning="state.loading" >
      <div class="topology-preview" >
        <a-row class="zoom-navbar" justify="center" >
          <a-col  >
            <a-space>
              <a-tooltip>
                <template #title>放大</template>
                <zoom-in-outlined  @click="zoomIn" :style="{fontSize: '20px', cursor: 'pointer'}" />
              </a-tooltip>
              <span>{{zoomCount}}%</span>
              <a-tooltip>
                <template #title>缩小</template>
                <zoom-out-outlined  @click="zoomOut" :style="{fontSize: '20px', cursor: 'pointer'}" />
              </a-tooltip>
              <a-button @click="resetZoom" >重置</a-button>
            </a-space>
          </a-col>
        </a-row>
        <vue-tree
          style="width: 1000px; height: 600px; border: 1px solid gray;"
          :dataset="treeData.richMediaData"
          :config="treeData.treeConfig"
          id="vueTreeRef"
          ref="vueTreeRef"
        >
          <template v-slot:node="{ node, collapsed }">
            <a-row
              class="rich-media-node"
            >
              <a-col :span="24"  >
                <!--    📦 -->
                <div class="label" >
                  <div style="width: 100%; text-align: center;" >{{node.value}}</div>
                  <div style="width: 100%; text-align: center;" v-if="node.modelLabel" > 模型名： {{node.modelLabel}}</div>
                  <div style="width: 100%; text-align: center;" v-if="node.deviceLabel" >设备名:  {{node.deviceLabel}}</div>
                </div>
              </a-col>
              <a-col :span="24" >
                <div >
                  <div v-if="node.transportType" >协议：{{node.transportType}}</div>
                  <div v-if="node.payloadType" >格式：{{node.payloadType}}</div>
                </div>
                <div v-if="node.deviceStatus" class="deviceStatus" >
                  状态：
                  <a-tag :color="DeviceContriller.deviceStatusMap.get(node.deviceStatus)?.color" >
                    {{ DeviceContriller.deviceStatusMap.get(node.deviceStatus)?.name}}
                  </a-tag>
                </div>
                <div v-if="node.deviceStatus && node.lastConnectTs"  class="ts">
                  <div>时间：{{ dayjs(node.lastConnectTs).format('YYYY-MM-DD HH:mm:ss') }}</div>
                  <div style="width: 100%;text-align: center;" >~</div>
                  <div style="width: 100%;text-align: right;" >{{ dayjs(node.lastActivityTs).format('YYYY-MM-DD HH:mm:ss')}}</div>
                </div>
              </a-col>
              <!-- {{node.deviceLabel}} -->
            </a-row>
          </template>
        </vue-tree>
      </div>
    </a-spin>

  </a-card>
</template>

<script lang="ts" setup >
import { DeviceContriller, ModelController } from '@/controller'
import { reactive, onMounted, watch, ref, onUnmounted, onBeforeUnmount } from 'vue'
import VueTree from '@ssthouse/vue3-tree-chart'
import '@ssthouse/vue3-tree-chart/dist/vue3-tree-chart.css'
import { AppstoreOutlined, ZoomInOutlined, ZoomOutOutlined } from '@ant-design/icons-vue'
import html2canvas from 'html2canvas'
import dayjs from 'dayjs'

const state = reactive<{
  modelId: string,
  modelList: IOT.API.MODEL.Model[],
  dataSource: {
    gatewayDevice: any[]
    model: IOT.API.MODEL.Model[]
    subDevice: IOT.API.DEVICE.Device[]
  },
  loading: false
}>({
  modelId: '',
  loading: false,
  modelList: [],
  dataSource: {
    gatewayDevice: [],
    model: [],
    subDevice: []
  }
})

const vueTreeRef = ref('')

const zoomCount = ref(100)

const treeData = reactive({
  richMediaData: {
    name: '产品模型',
    value: '产品模型'
  },
  treeConfig: { nodeWidth: 190, nodeHeight: 80, levelHeight: 200 }
}
)

const zoomIn = () => {
  zoomCount.value += 5

  try {
    vueTreeRef.value.zoomIn()
  } catch (error) {

  }
}

const zoomOut = () => {
  zoomCount.value -= 5
  try {
    vueTreeRef.value.zoomOut()
  } catch (error) {

  }
}

const resetZoom = () => {
  zoomCount.value = 100
}

const scaleHandle = (event) => {
  if (event.deltaY > 0) {
    zoomOut()
  } else {
    zoomIn()
  }
}

window.addEventListener('wheel', scaleHandle)

onUnmounted(() => {
  window.removeEventListener('wheel', scaleHandle)
})

watch(
  () => state.modelId,
  () => getDeviceTopology()
)

function exportDomToImage () {
  html2canvas(document.getElementById('vueTreeRef')).then(canvas => {
    const imgData = canvas.toDataURL('image/png')
    const link = document.createElement('a')
    link.href = imgData
    link.download = 'exported-image.png'
    link.click()
  })
}

const getDeviceTopology = async () => {
  state.loading = true
  const { data } = await DeviceContriller.getDeviceTopology(state.modelId)
  const { gatewayDevice, model, subDevice } = data

  const obj = {
    name: '产品模型',
    value: '产品模型',
    children: model
  }

  obj.children.forEach(model => {
    model.children = []
    gatewayDevice.forEach(item => {
      if (item.modelId === model.id) {
        model.children.push(item)
      }
      item.children = []
      subDevice.forEach(sd => {
        if (sd.gatewayId === item.id) {
          item.children.push(sd)
        }
      })
    })
  })

  treeData.richMediaData = obj
  state.loading = false
}

const getModelList = async () => {
  const { data } = await ModelController.list()
  state.modelList = data
  if (data.length) {
    state.modelId = data[0].id
  }
}

onMounted(() => {
  getModelList()
})

</script>

<style lang="less" scoped >
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.rich-media-node {
  width: 300px;
  padding: 8px;
  color: white;
  background-color: #1890ff;
  border-radius: 4px;
  a-col {
    display: flex;
    justify-content: center;
    align-items: center;
    .label {
    }
    .deviceStatus {
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .ts {
      display: flex;
      align-items: center;
      justify-content: center;
    }
  }
}

#vueTreeRef {
  position: relative;
  z-index: 1;
}

.topology-preview {
  position: relative;
  width: 1000px;
  margin-top: 20px;
  .zoom-navbar {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 50px;
    background-color: #f6f6f6;
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 2;
  }
}

</style>
