<script setup lang="ts">
import { tryOnMounted, tryOnUnmounted } from '@vueuse/core';
import { GraphModel } from '@logicflow/core';
import { VueNodeModel } from '@logicflow/vue-node-registry';

import { useEventListener } from '@/libs/logic-flow/use';

import { ID_End, ID_Start } from './config';
import type { FlowNodeProperties } from './index';
import FlowNodeInlay from './FlowNodeInlay.vue';

type NodeModelInstance = InstanceType<typeof VueNodeModel>;
type GraphModelInstance = InstanceType<typeof GraphModel>;

defineOptions({
  name: 'LogicFlowNode',
});

const getNode = inject<() => NodeModelInstance>('getNode');
const getGraph = inject<() => GraphModelInstance>('getGraph');

const text = ref('');
const id = ref('');

const popover = ref(false);

const properties = ref<FlowNodeProperties>({
  width: 0,
  height: 0,
  radius: 0,
  iconBackground: 'transparent',
  iconColor: '#000',
});

const appendNodes = shallowRef<{ id: string; text: string }[]>([]);
const linkNodes = shallowRef<{ id: string; text: string; disabled?: boolean }[]>([]);

let mouseenterTimer: ReturnType<typeof setTimeout>;
tryOnMounted(() => {
  const model = getNode?.()!;
  const graph = getGraph?.()!;

  id.value = model.id;
  text.value = model.text.value;

  updateProperties(model.getProperties());
  useEventListener(
    graph.eventCenter,
    'node:properties-change',
    (event) => updateProperties(event.properties),
    (event) => event.id === id.value
  );
  useEventListener(
    graph.eventCenter,
    'node:dnd-drag',
    () => {
      popover.value = false;
      clearTimeout(mouseenterTimer);
    },
    (event) => event.data?.id === id.value
  );
  useEventListener(
    graph.eventCenter,
    'node:drag',
    () => {
      popover.value = false;
      clearTimeout(mouseenterTimer);
    },
    (event) => event.data?.id === id.value
  );
  /*useEventListener(
    graph.eventCenter,
    'node:mouseenter',
    (event) => {
      mouseenterTimer = setTimeout(() => {
        popover.value = true;
        const quickNodes = event.data.properties?.quickNodes ?? [];
        appendNodes.value = [...quickNodes];
        linkNodes.value = [];
        const outgoing = graph.getNodeOutgoingNode(event.data.id).map((node) => node.id);
        for (const { id } of graph.nodes) {
          const index = appendNodes.value.findIndex((node) => node.id === id);
          if (index !== -1) {
            const node = appendNodes.value.splice(index, 1).at(0);
            linkNodes.value.push({ ...node, disabled: outgoing.includes(node.id) });
          }
        }
        triggerRef(appendNodes);
        triggerRef(linkNodes);
      }, 100);
    },
    (event) => event.data?.id === id.value
  );*/
});
tryOnUnmounted(() => { popover.value = false; });

function updateProperties(props: FlowNodeProperties) {
  properties.value = Object.assign(properties.value, props);
}

function configure(event: MouseEvent) {
  const data = getNode?.().getData();
  // @ts-ignore
  if (data) getGraph?.()?.eventCenter?.emit('node:click', { data, e: event, position: void 0 });
  popover.value = false;
}

function remove() {
  const data = getNode?.().getData();
  if (data) getGraph?.()?.deleteNode(data.id);
  popover.value = false;
}

function link(targetNodeId: string) {
  const data = getNode?.().getData();
  if (data)
    getGraph?.()?.eventCenter?.emit('connection:quick', {
      sourceNodeId: data.id,
      targetNodeId,
    });
  popover.value = false;
}
</script>

<template>
  <FlowNodeInlay v-if="id === ID_End" class="node" :id :text v-bind="properties"></FlowNodeInlay>
  <a-popover v-else :title="text" placement="right" trigger="contextmenu" v-model:open="popover" :mouseEnterDelay="1">
    <template #content>
      <div class="popover-content-wrapper">
        <a-space wrap>
          <a-button type="primary" v-if="properties?.configurable" @click="configure">配置数据</a-button>
          <a-button danger :disabled="id === ID_End || id === ID_Start" @click.prevent="remove">移除节点</a-button>
        </a-space>
        <div style="margin-top: 14px" v-if="appendNodes.length">
          <div class="title">添加下流节点</div>
          <a-space wrap>
            <a-button v-for="node in appendNodes" :key="node.id" type="dashed" @click.prevent="link(node.id)">{{ node.text }}</a-button>
          </a-space>
        </div>
        <div style="margin-top: 14px" v-if="linkNodes.length">
          <div class="title">连接下流节点</div>
          <a-space wrap>
            <a-button v-for="node in linkNodes" :key="node.id" :disabled="node.disabled" type="dashed" @click.prevent="link(node.id)">{{ node.text }}</a-button>
          </a-space>
        </div>
      </div>
    </template>
    <FlowNodeInlay class="node" :id :text v-bind="properties"></FlowNodeInlay>
  </a-popover>
</template>

<style scoped lang="scss">
.node {
  --width: calc(v-bind(properties.width) * 1px);
  --height: calc(v-bind(properties.height) * 1px);
  --radius: calc(v-bind(properties.radius) * 1px);
  --icon-background: v-bind(properties.iconBackground);
  --icon-color: v-bind(properties.iconColor);
}

.popover-content-wrapper {
  max-width: 300px;
  .title {
    margin-bottom: 8px;
    color: rgba(0, 0, 0, 0.88);
    font-weight: 600;
  }
}
</style>
