<template>
    <div id="jfDragWrapPaper">
        <div id="jfWrapPaper"
             class="jf-wrap-paper"
        >
            <div id="jsonflowMainPaper" @dragover="methods.allowDrop" @drop="methods.drop"></div>
            <div class="horizontal-line-x"></div>
            <div class="vertical-line-y"></div>
        </div>
        <div id="minimapPaperView" class="jsonflow-navigator"></div>
        <div class="container-scale">
            <el-button icon="ZoomIn" circle size="small" type="default"
                       @click="methods.enlargePaper"></el-button>
            <span>{{ data.container.scaleShow }}% </span>
            <el-button icon="ZoomOut" circle size="small" type="default"
                       @click="methods.narrowPaper"></el-button>
        </div>
        <!-- 选择连接的节点 -->
        <el-dialog
                v-model="data.showSetConnectNode" v-if="data.showSetConnectNode"
                top="20px"
                width="50%"
                title="请选择连接到的节点"
                append-to-body>
            <el-form label-position="left" class="flow-config-attr" label-width="170px">
                <el-form-item label="连接到的节点">
                    <el-select class="input-attr" placeholder="请选择连接到的节点" style="width: 80%!important;"
                               @change="methods.doConnectNode"
                               v-model="data.toFlowNodeId"
                               filterable clearable>
                        <el-option
                                v-for="(item, index) in data.flowNodeIds"
                                :key="item.id"
                                :label="item.nodeName"
                                :value="item.id">
                        </el-option>
                    </el-select>
                    <el-tooltip placement="top">
                        <template #content>从当前节点连接到目标节点</template>
                        <el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
                    </el-tooltip>
                </el-form-item>
            </el-form>
        </el-dialog>

        <!-- 选择连线的起始节点 -->
        <el-dialog
                v-model="data.showLinkFlowNodeIds" v-if="data.showLinkFlowNodeIds"
                top="20px"
                width="50%"
                :title="'请选择连接到的' + (data.modifyPointType === '0' ? '起点' : '终点')"
                append-to-body>
            <el-form label-position="left" class="flow-config-attr" label-width="170px">
                <el-form-item label="起始节点（可修改）" v-if="data.modifyPointType ==='0'">
                    <el-select class="input-attr" style="width: 80%!important;"
                               v-model="data.fromFlowNodeId"
                               @change="methods.changeLinkFlowNodeIds('0')"
                               filterable clearable>
                        <el-option
                                v-for="(item, index) in data.fromFlowNodeIds"
                                :key="item.id"
                                :label="item.nodeName"
                                :value="item.id">
                        </el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="目标节点（可修改）" v-if="data.modifyPointType ==='1'">
                    <el-select class="input-attr" style="width: 80%!important;"
                               v-model="data.toFlowNodeId"
                               @change="methods.changeLinkFlowNodeIds('1')"
                               filterable clearable>
                        <el-option
                                v-for="(item, index) in data.toFlowNodeIds"
                                :key="item.id"
                                :label="item.nodeName"
                                :value="item.id">
                        </el-option>
                    </el-select>
                </el-form-item>
            </el-form>
        </el-dialog>
        <vue-context-menu
                :contextMenuData="data.paperContMenuData"
                @flowInfo="methods.flowInfo"
                @paste="methods.paste"
        >
        </vue-context-menu>
        <vue-context-menu
                :contextMenuData="data.nodeContMenuData"
                @setNodeAttr="methods.setNodeAttr('0')"
                @copyNode="methods.copyNode"
                @deleteNode="methods.deleteNode"
                @setConnectNode="methods.setConnectNode"
        >
        </vue-context-menu>
        <vue-context-menu
                :contextMenuData="data.nodeConnectMenuData"
                @setSerialNode="methods.setSerialNode"
                @setSerialGate="methods.setSerialGate"
                @setParallelNode="methods.setParallelNode"
                @setParallelGate="methods.setParallelGate"
                @setConnectNode="methods.setConnectNode"
        >
        </vue-context-menu>
        <vue-context-menu
                :contextMenuData="data.linkContMenuData"
                @deleteLink="methods.deleteLink"
                @setLinkAttr="methods.setNodeAttr('1')"
                @modifySourceNode="methods.handleLinkFlowNodeIds('0')"
                @modifyTargetNode="methods.handleLinkFlowNodeIds('1')"
        >
        </vue-context-menu>
    </div>
</template>

<script setup lang="ts" name="FlowArea">
    import {flowConfig} from "../config/flow-config";
    import {utils} from "../utils/common";
    import {useI18n} from "vue-i18n";
    import {useMessage, useMessageBox} from "/@/hooks/message";
    import {notifyLeft} from "/@/flow";
    import {CommonNodeType, HighNodeType} from "../config/type";
    import {hideVueContextmenuName} from "/@/flow/utils";
    import {validateNull} from "/@/utils/validate";
    import {changeLinkFlowNodeIds, handleLinkFlowNodeIds, validateNodeType} from "./index";

    // 引入组件
    const VueContextMenu = defineAsyncComponent(() => import('../../components/contextmenu/index.vue'));

    const {t} = useI18n();
    const {proxy} = getCurrentInstance();
    const $message = useMessage();
    const $emit = defineEmits(["removeEleTools", "showAttrConfig", "initJsonFlow"]);
    const props = defineProps({
        dragInfo: {
            type: Object,
            default: null,
        },
        currSelect: {
            type: Object,
            default: {},
        }
    });
    const data = reactive({
        container: {
            scaleShow: utils.mul(flowConfig.defaultStyle.containerScale.init, 100)
        },
        paperContMenuData: flowConfig.contextMenu.container,
        nodeContMenuData: flowConfig.contextMenu.node,
        nodeConnectMenuData: flowConfig.contextMenu.nodeConnect,
        linkContMenuData: flowConfig.contextMenu.link,
        clipboard: {},
        showSetConnectNode: false,
        showLinkFlowNodeIds: false,
        toFlowNodeId: null,
        flowNodeIds: [],
        modifyPointType: null,
        fromFlowNodeId: null,
        fromFlowNodeIds: [],
        toFlowNodeIds: []
    })
    const methods = {
        allowDrop(e) {
            e.preventDefault();
        },
        drop(e) {
            // 增加节点
            window._jfOperate.dropNewNode(e, props.dragInfo, true);
        },
        // 画布放大
        enlargePaper() {
            data.container.scaleShow = window._jfOperate.zoomOut();
        },
        // 画布缩小
        narrowPaper() {
            let zoomIn = window._jfOperate.zoomIn();
            data.container.scaleShow = parseInt(zoomIn)
        },
        // 画布右健
        showPaperContMenu(e) {
            let event = window.event || e;

            event.preventDefault();
            hideVueContextmenuName()
            let x = event.clientX;
            let y = event.clientY;
            data.paperContMenuData.axis = {x, y};
        },
        // 流程图信息
        flowInfo() {
            $message.info(
                "当前流程图中有 " +
                window._jfGraph.getElements().length +
                " 个节点，有 " +
                window._jfGraph.getLinks().length +
                " 条连线。"
            );
        },
        handleFlowNodeIds() {
            data.flowNodeIds = []
            let models = window._jfGraph.getElements();
            if (validateNull(models)) return
            models.forEach(each => {
                if (!validateNodeType(each)) return
                if (props.currSelect.id !== each.id) {
                    let id = each.id
                    let nodeName = each.attributes.attrs.label.text + "（ID:" + id + "）"
                    data.flowNodeIds.push({id, nodeName})
                }
            })
        },
        // 粘贴
        paste() {
            let e = window.event;
            let b = Object.keys(data.clipboard).length === 0;
            if (b) {
                $message.info("请将鼠标放节点上, 右键菜单复制节点");
                hideVueContextmenuName()
                return
            }
            let newNode = data.clipboard.clone()
            window._jfOperate.pasteNode(newNode, e);
            data.clipboard = {}
            hideVueContextmenuName()
        },
        // 节点右键
        showNodeContMenu(e) {
            let event = window.event || e;

            event.preventDefault();
            hideVueContextmenuName()
            let x = event.clientX;
            let y = event.clientY;
            data.nodeContMenuData.axis = {x, y};
        },
        // 复制节点
        copyNode() {
            data.clipboard = {};
            if (methods.validateCurrSelect("0")) {
                return
            }
            data.clipboard = props.currSelect;
            hideVueContextmenuName()
        },
        // 删除节点
        deleteNode() {
            if (methods.validateCurrSelect("0")) {
                return
            }
            props.currSelect.remove()
            $emit("removeEleTools");
        },
        setNodeAttr(type) {
            if (methods.validateCurrSelect(type)) {
                return
            }
            $emit("showAttrConfig", true);
        },
        // 连接线右键
        showLinkContMenu(e) {
            let event = window.event || e;

            event.preventDefault();
            event.stopPropagation();
            hideVueContextmenuName()
            let x = event.clientX;
            let y = event.clientY;
            data.linkContMenuData.axis = {x, y};
        },
        // 删除线
        deleteLink() {
            if (methods.validateCurrSelect("1")) {
                return
            }
            props.currSelect.remove()
            $emit("removeEleTools");
        },
        validateCurrSelect(type) {
            let b = Object.keys(props.currSelect).length === 0;
            if (b !== true) return false
            if (type === '0') {
                notifyLeft('请先选择节点', 'warning')
            } else {
                notifyLeft('请先移动到连线上方', 'warning')
            }
            return true
        },
        // 节点连接右键
        showNodeConnectMenu(params, e) {
            let event = window.event || e;

            hideVueContextmenuName()
            let x = event.clientX;
            let y = event.clientY;
            data.nodeConnectMenuData.axis = {x, y};
            data.nodeConnectMenuData.params = params;
        },
        setSerialNode() {
            methods.connectAction({belongTo: "commonNodes", type: CommonNodeType.SERIAL})
        },
        setParallelNode() {
            methods.connectAction({belongTo: "commonNodes", type: CommonNodeType.PARALLEL})
        },
        setSerialGate() {
            methods.connectAction({belongTo: "highNodes", type: CommonNodeType.SERIAL})
        },
        setParallelGate() {
            methods.connectAction({belongTo: "highNodes", type: CommonNodeType.PARALLEL})
        },
        setConnectNode() {
            if (methods.hideValidateCurrSelect("0")) {
                return
            }
            methods.handleFlowNodeIds()
            data.toFlowNodeId = null
            data.showSetConnectNode = true
        },
        doConnectNode(val) {
            if (methods.hideValidateCurrSelect("0")) {
                return
            }
            let simpleMode = window._flowConfig.globalConfig.isSimpleMode;
            if (simpleMode !== '1') {
                data.nodeConnectMenuData.params = {view: {model: props.currSelect}}
            }
            useMessageBox()
                .confirm('是否确认连接到当前选中的节点?')
                .then(() => {
                    let params = data.nodeConnectMenuData.params;
                    params.toFlowNodeId = val
                    window._jfOperate.doConnectNode(params)
                    data.showSetConnectNode = false
                    if (simpleMode !== '1') {
                        notifyLeft('专业模式不会自动调整连线轨迹，有必要时请手动调整', 'warning', 3000)
                    }
                })
        },
        connectAction(dragInfo) {
            if (methods.hideValidateCurrSelect("0")) {
                return
            }
            let params = data.nodeConnectMenuData.params;
            window._jfOperate.connectAction(params, dragInfo)
        },
        hideValidateCurrSelect(type) {
            hideVueContextmenuName()
            return methods.validateCurrSelect(type);
        },
        changeLinkFlowNodeIds(type) {
            if (methods.hideValidateCurrSelect("1")) {
                return
            }
            changeLinkFlowNodeIds(data, props)
            data.showLinkFlowNodeIds = false
        },
        handleLinkFlowNodeIds(type) {
            if (methods.hideValidateCurrSelect("1")) {
                return
            }
            data.modifyPointType = type
            handleLinkFlowNodeIds(data, props)
            data.showLinkFlowNodeIds = true
        },
    }

    onMounted(() => {
        nextTick(() => {
            $emit("initJsonFlow");
        })
    });

    // 暴露变量
    defineExpose({
        showPaperContMenu: methods.showPaperContMenu,
        showNodeContMenu: methods.showNodeContMenu,
        showNodeConnectMenu: methods.showNodeConnectMenu,
        showLinkContMenu: methods.showLinkContMenu,
    });
</script>

<style lang="scss">
  @import "../assets/style/flow-area.scss";
  @import "../assets/style/flow-paper.css";
</style>
