<template>
  <div class="relative h-full w-full">
    <el-button type="primary" @click="onBack" class="absolute top-0 z-99">
      <i class="i-line-md:arrow-left"></i>返回站点数据
    </el-button>
    <el-empty v-if="!topologyTree && !loading" class="w-full h-full"></el-empty>
    <div
      id="container"
      class="w-full h-full"
      v-loading="loading"
      element-loading-text="设备加载中请稍等..."
      style="width: 100%;height: 100%">
    </div>
  </div>

  <detail-drawer ref="detailDrawerRef"/>
</template>

<script setup lang="ts">
import { DeviceType, NODE_SIZE } from "./utils";
import { useG6 } from "@/hooks/useG6";
import Node from './components/Node.vue'
import { flattenTree } from "@/views/testG6/utils";
import { type PluginOptions } from "@antv/g6"
import type { IDevice, IOfflineDevice, IOnlineDevice } from "@/views/stationData/type";
import { getPointGroup, type IPointGroupParams, type IPointGroupOV } from "@/api/module/transfer";
import DetailDrawer from "./components/detailDrawer.vue";
import { VueNode } from "g6-extension-vue";

const router = useRouter()

const route = useRoute()
const deviceInfo = route.query?.deviceInfo
  ? JSON.parse(route.query?.deviceInfo as string)
  : {} as unknown as IDevice & { isonLine: boolean, siteName: string }

const detailDrawerRef = ref<InstanceType<typeof DetailDrawer>>()
const topologyTree = ref<IPointGroupOV>()
const loading = ref(true)

async function loadDeviceTopology() {
  const params: IPointGroupParams = {}
  if (deviceInfo.isonLine) {
    const onlineDevice = deviceInfo as IOnlineDevice
    params.isLocal = false
    params.host = onlineDevice.clientIp
  } else {
    const offlineDevice = deviceInfo as unknown as IOfflineDevice & { siteName: string }
    params.sn = offlineDevice.sn
    params.site = offlineDevice!.siteName
    params.isLocal = true
  }

  const res = await getPointGroup(params)
  if (res.code === 0) {
    topologyTree.value = {
      id: deviceInfo.sn,
      ip: deviceInfo.ip,
      name: deviceInfo?.sn,
      cnName: deviceInfo?.name ?? deviceInfo?.sn,
      port: deviceInfo.port,
      slave_addr: 'root',
      type: deviceInfo?.type ?? 'emu',
      children: []
    }
    topologyTree.value.children = Array.isArray(res?.data) ? res.data : []
  }
}

const getNodeData = (target: VueNode) => {
  const targetId = target.config.id
  const context = target.config!.context
  return context.model.getNodeData(targetId).find((r: any) => r.id === targetId)
}

const canvas = ref<HTMLElement | undefined>(undefined)

const plugins: PluginOptions = [
  {
    type: 'contextmenu',
    enable: (e: any) => e.targetType === 'node',
    getItems: (e: any) => {
      const { data } = getNodeData(e.target)
      const menu = [{ name: '查看详情', value: 'detail' }]
      if (data.type === DeviceType.bms) {
        menu.unshift({ name: '固件升级', value: 'firmwareUpdate' })
      }
      return menu;
    },
    onClick: onContextmenuClick,
  },
  {
    type: 'tooltip',
    enable: (e: any) => e.targetType === 'node',
    getContent: (e: any, items: any) => {
      return `<div>${items[0].data.cnName}</div>`;
    },
  },
]

function onContextmenuClick(e: string, item: HTMLElement, current: any) {

  switch (e) {
    case 'detail':
      onDetail(item, current)
      break;
    case 'firmwareUpdate':
      onFirmwareUpdate(item, current)
      break;
    default:
      break;
  }
}

function init() {
  if (!topologyTree.value) return
  const filteredTree = filterTree(topologyTree.value)
  const device = flattenTree([filteredTree])

  const { container, graph } = useG6({
    tree: device,
    nodeComponent: Node,
    nodeSize: NODE_SIZE
  }, plugins)
  canvas.value = container.value
  graph.render();
}

function onDetail(item: HTMLElement, current: any) {
  const { data } = getNodeData(current)
  const device = deviceInfo as unknown as IDevice & {
    isonLine: boolean
    siteName: string
  }
  detailDrawerRef.value?.open(device, data)
}

function onFirmwareUpdate(item: HTMLElement, current: any) {
  const { data } = getNodeData(current)
  window.open(`http://${data.ip}:${data.port}`, '_blank', 'noopener');
}

onMounted(async () => {
  await loadDeviceTopology()
  loading.value = false
  init()
})

function filterTree(node: IPointGroupOV) {
  if (node.type === 'bms_cluster' && Array.isArray(node.children)) {
    if (node.children.length > 1) {
      const customNode = node.children[0] as any
      node.children.forEach(r => {
        r.customCnName = r.cnName
      })
      customNode.cnName = `${node.children[0].cnName} ~ ${node.children[node.children.length - 1].cnName}`
      customNode.customNode = true
      customNode.brother = node.children
      node.children = [customNode]
    }
  }

  if (Array.isArray(node.children)) {
    node!.children = node.children.map((child: any) => {
      child.parentName = node.name
      return filterTree(child)
    })
  }

  return node
}

function onBack() {
  router.push('/station')
}
</script>

<style scoped lang="scss">

</style>