<template>
  <div id="container"></div>
</template>

<script>
export default {
  name: 'VideoLineGraph'
}
</script>

<script setup>
import { ref, watch, onMounted } from 'vue'
import G6 from '@antv/g6'
import useGraphHandle from './hooks/useGraphHandle.js'
import useGraphPlugins from './hooks/useGraphPlugins.js'
import useGrapheBehavior from './hooks/useGrapheBehavior.js'
import useGrapheRegisterNode from './hooks/useGrapheRegisterNode.js'
import { postMessage } from '../utils/iframePip.js'

const { Util } = G6

const props = defineProps({
  // 初始化图表数据
  graphData: {
    type: Object,
    default: () => ({})
  },
  // 是否需要对外发送信息
  ifSendMsg: {
    type: Boolean,
    default: false
  },
  // 外部调用者传递的数据, ifSendMsg 为 false时，说明没有外部调用，此参数就无意义
  pipData: {
    type: Object,
    default: () => ({})
  }
})

// 流程图对外发送信息
const graphPostMessage = (data) => {
  props.ifSendMsg && postMessage(data)
}

const emits = defineEmits('onEdit', 'onSave')

const _graphData = ref({})

watch(
  () => props.graphData,
  (val) => {
    // 外部想要切换流程图数据
    _graphData.value = val
    try {
      graph.changeData(val, true)
      graph.fitCenter()
      graphPostMessage({
        msgType: 'ok',
        content: {
          callBackType: props.pipData.msgType,
          msg: '操作成功'
        }
      })
    } catch (error) {
      graphPostMessage({
        msgType: 'fail',
        content: {
          callBackType: props.pipData.msgType,
          msg: `操作失败：${error}`
        }
      })
    }
  }
)

watch(
  () => props.pipData,
  (val) => {
    // 外部想要获取流程图数据
    if (val.msgType === 'graph_get_data') {
      try {
        graphPostMessage({
          msgType: 'graph_get_data',
          content: JSON.parse(JSON.stringify(graph.save()))
        })
        graphPostMessage({
          msgType: 'ok',
          content: {
            callBackType: 'graph_get_data',
            msg: '操作成功'
          }
        })
      } catch (error) {
        graphPostMessage({
          msgType: 'fail',
          content: {
            callBackType: props.pipData.msgType,
            msg: `操作失败：${error}`
          }
        })
      }
    }
  }
)

let graph = null
// 注册自定义节点
useGrapheRegisterNode(G6)
// 注册自定义事件
const { initHandle } = useGraphHandle(emits)
// 注册流程图插件
const {
  // toolbar,
  grid,
  menu
} = useGraphPlugins()
// 注册自定义交互
const { behaviorList } = useGrapheBehavior(G6)

// 初始化流程图
const initGraph = () => {
  const container = document.getElementById('container')
  const width = container.scrollWidth
  const height = (container.scrollHeight || 500) - 20
  graph = new G6.TreeGraph({
    container: 'container', //容器 id
    width,
    height,
    enabledStack: false, // 是否启用历史记录，这里先不用，记录的状态得手动设定，这里用自带得不太好用
    fitCenter: true, // 初始化在中心展示
    // renderer: 'svg',     // 渲染图形得类型
    animate: true, // 是否用动画
    animateCfg: {
      //动画配置
      duration: 300
    },
    modes: {
      //交互
      default: behaviorList
    },
    plugins: [grid, menu], // 插件
    defaultNode: {
      // 默认节点样式
      type: 'rect',
      size: 40,
      anchorPoints: [
        [0, 0.5],
        [1, 0.5]
      ]
    },
    defaultEdge: {
      // 默认线样式
      type: 'cubic-horizontal',
      color: '#121212',
      style: {
        lineWidth: 2
      }
    },
    layout: {
      // 布局配置
      type: 'mindmap',
      direction: 'H',
      // 计算图形高度
      getHeight: (node) => {
        return node.type === 'jump-node' ? 28 : 88
      },
      // 计算图形宽度
      getWidth: (node) => {
        const data = node.data || {}
        const label = data.jumpNodeName || '右键选择跳转目标'
        const jumpNodeWidth = Util.getTextSize(label, 14)[0] + 24
        return node.type === 'jump-node' ? jumpNodeWidth : 180
      },
      // 垂直方向上节点的间隔
      getVGap: () => {
        return 20
      },
      // 水平方向上节点的间隔
      getHGap: () => {
        return 80
      },
      // 方向
      getSide: () => {
        return 'right'
      }
    }
  })

  graph.data(props.graphData) // 读取 Step 2 中的数据源到图上
  graph.render() // 渲染图
  graph.fitCenter()
  initHandle(graph, container)
}

onMounted(() => {
  initGraph()
  // 外侧监听可能还没初始化好，这里等一下
  setTimeout(() => {
    graphPostMessage({
      msgType: 'graph_init',
      content: '图表初始化成功'
    })
  }, 250)
})
// 获取到流程图数据
const getGraphData = () => {
  return graph.save()
}

defineExpose({
  getGraphData
})
</script>

<style lang="scss" scoped>
#container {
  width: 100vw;
  height: 100vh;
}
:deep(.g6-component-contextmenu) {
  padding: 0;
  .menu-list {
    list-style: none;
    padding: 0;
    .menu-item {
      display: flex;
      align-items: center;
      padding: 8px 16px;
      cursor: pointer;
      color: #333;
      font-size: 14px;
      border-radius: 4px;
      &:hover {
        background-color: #f7f7f7;
        color: rgb(95, 149, 255);
      }
    }
    .menu-item-split {
      margin: 4px 0;
      width: 100%;
      height: 1px;
      background-color: #d8d8d8;
    }
  }
}
</style>
