<script setup lang="ts">
import { ref, watch, onMounted } from 'vue'
import { use } from 'echarts/core'
import VChart from 'vue-echarts'
import { GraphChart } from 'echarts/charts'
import { TitleComponent, TooltipComponent } from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'

use([GraphChart, TitleComponent, TooltipComponent, CanvasRenderer])

interface KnowledgeNode {
  id: string
  label: string
  children?: KnowledgeNode[]
}

const props = defineProps<{ treeData: KnowledgeNode[] }>()
const collapsedSet = ref<Set<string>>(new Set())
const chartOption = ref({})

function treeToGraph(tree: KnowledgeNode[]) {
  const nodes: any[] = []
  const links: any[] = []
  function traverse(node: KnowledgeNode, parent: KnowledgeNode | null = null) {
    nodes.push({
      id: node.id,
      name: node.label,
      symbolSize: 50,
      itemStyle: { color: collapsedSet.value.has(node.id) ? '#91cc75' : '#fac858' },
    })
    if (parent) {
      links.push({
        source: parent.id,
        target: node.id,
      })
    }
    if (!collapsedSet.value.has(node.id) && node.children) {
      node.children.forEach((child) => traverse(child, node))
    }
  }
  tree.forEach((root) => traverse(root))
  return { nodes, links }
}

function updateOption() {
  const { nodes, links } = treeToGraph(props.treeData)
  chartOption.value = {
    backgroundColor: '#222',
    series: [
      {
        type: 'graph',
        layout: 'force',
        roam: true,
        data: nodes,
        links: links,
        label: {
          show: true,
          color: '#fff',
        },
        force: {
          repulsion: 200,
          edgeLength: 100,
        },
        lineStyle: {
          color: '#aaa',
        },
      },
    ],
  }
}

function onChartClick(params: any) {
  if (params.dataType === 'node') {
    const nodeId = params.data.id
    if (collapsedSet.value.has(nodeId)) {
      collapsedSet.value.delete(nodeId)
    } else {
      collapsedSet.value.add(nodeId)
    }
    updateOption()
  }
}

watch(() => props.treeData, updateOption, { deep: true })
onMounted(updateOption)
</script>

<template>
  <VChart :option="chartOption" autoresize style="width: 100%; height: 100%" @click="onChartClick" />
</template>
