import React from "react";
import GraphNode from "./GraphNode";
import GraphEdge from "./GraphEdge";
import { initGraph } from './creatGraph'
import registerTools from './registerTools'
import eventBus from '../script/event'
import CraftOtype from '../script/craftOtype';
let icon = `<svg t="1632908927008" class="icon" style="width: 1em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5464"><path d="M512 2.27555559a509.72444441 509.72444441 0 1 0 0 1019.44888888A509.72444441 509.72444441 0 0 0 512 2.35877613z m0 932.8997593a423.34175471 423.34175471 0 1 1 0.16644089-846.60028994A423.34175471 423.34175471 0 0 1 512 935.2585341z m181.5867323-665.5128794h-67.65811822a8.98779492 8.98779492 0 0 0-8.1555912 4.99321856L514.74627013 479.46085605h-3.9113546L407.80816269 274.65565405a9.15423463 9.15423463 0 0 0-8.07237064-4.99321856h-69.07286418a9.15423463 9.15423463 0 0 0-7.9891501 13.56491212l126.74454286 233.01688891h-69.90506646a9.15423463 9.15423463 0 0 0-9.07101416 9.071014v34.03711041c0 4.99321853 4.1610159 9.15423463 9.15423464 9.15423477h92.95709524v47.01947895H379.59647465a9.15423463 9.15423463 0 0 0-9.15423464 9.15423569v33.95388877c0 4.99321853 4.1610159 9.15423463 9.15423464 9.15423593h92.95709524v77.39489482c0 4.99321853 4.07779555 9.15423463 9.07101397 9.15423465h61.74947561c4.99321853 0 9.15423463-4.1610159 9.15423458-9.15423465v-77.39489482h93.20675558c5.07643909 0 9.15423463-4.1610159 9.15423576-9.15423593v-33.95388877a9.15423463 9.15423463 0 0 0-9.15423576-9.15423569h-93.2067555v-47.18592007h93.2067555c5.07643909 0 9.15423463-4.1610159 9.15423576-9.15423455V525.31525071a9.15423463 9.15423463 0 0 0-9.15423576-9.1542345H575.24744082l126.4948827-233.01688901a9.81999733 9.81999733 0 0 0 1.08186387-4.32745706 9.32067557 9.32067557 0 0 0-9.23745494-9.15423465z" p-id="5465"></path></svg>`
export default class CraftView extends React.Component {
    graph = null;
    craft = null;
    constructor() {
        super();
        this.data = {};
        this.state = {
            currentProcedure: null,
            currentNode: null,
        }
    }
    componentWillUnmount() {
        if (this.graph) {
            this.graph.clearCells();
        }
        eventBus.off('selectDataType');
        eventBus.off('nodeMenuHandle')
    }
    loadCraft(craft) {  // 初始化
        // if ( !this.graph || !craft) return;
        // this.graph.clearCells();
        // this.craft = craft;
        // const { selection, disabled } = this.props;
        // for ( let i=0; i < craft.dag.nodes.length; i++ ) {
        //     this.graph.addNode(new GraphNode(craft.dag.nodes[i],selection,this.getNodes()))
        // }
        // for ( let i=0; i < craft.dag.links.length; i++ ) {
        //     this.graph.addEdge(new GraphEdge(craft.dag.links[i],(selection && !disabled),this.graph))
        // }
        if (!this.graph || !craft) return;
        this.graph.clearCells();
        this.craft = craft;
        const { selection, disabled } = this.props;

        let nodeList = [];
        for (const node of craft.dag.nodes) {
            nodeList.push(new GraphNode(node, selection, this.getNodes()))
        }
        this.graph.addNodes(nodeList)

        let edgeList = [];
        for (const link of craft.dag.links) {
            edgeList.push(new GraphEdge(link, (selection && !disabled), this.graph))
        }
        this.graph.addEdges(edgeList)
    }
    removeToolTips = () => {
        const { selection } = this.props;
        if (selection) {
            return
        }
        let tipsDom = document.getElementsByClassName('ant-tooltip');
        if (tipsDom && tipsDom.length) {
            for (let i = 0; i < tipsDom.length; i++) {
                const element = tipsDom[i];
                if (element && element.parentNode) {
                    element.parentNode.removeChild(element);
                }
            }
        }
    }
    addNode = (procedure) => {
        this.graph.addNode(new GraphNode(procedure, true, this.getNodes()))
    }
    addlink = (link) => {
        this.graph.addEdge(new GraphEdge(link, true))
    }
    updateMultiplicity = (link) => {
        let links = this.graph.getEdges();
        let currentLink = links.find(el => el.id === link.id);
        currentLink.setData(new GraphEdge(link, true))
        let dom = document.getElementsByClassName(`mark-item-${link.id}`)[0]
        let _multiplicity = link.multiplicity !== undefined ? link.multiplicity : 1;
        if (dom) {
            dom.innerHTML = `<span>${_multiplicity}</span>`
        }
    }
    getNodes = () => {  // 获取所有节点
        let nodes = [];
        nodes = [].concat([], this.props.dataInfo?.dag?.nodes)
        return nodes || [];
    }
    resetView = () => {
        this.graph.zoomTo(1);
        this.graph.centerContent() // 居中
    }
    cleanHistory = () => {  // 清掉历史
        if (this.graph) {
            this.graph.cleanHistory();
        }
    }
    selectProcedure = (procedure) => {
        const { selectProcedure } = this.props;
        if (typeof selectProcedure == 'function') {
            selectProcedure(procedure ? procedure.getProp() : null)
        }
    }
    selectGraph() {   // 选中操作
        // 单选
        this.graph.on('selection:changed', (args) => {
            args.added.forEach((cell) => {
                this.highlinghtNode(cell)
            })
            args.removed.forEach((cell) => {
                this.unHighlinghtNode(cell)
            })
        })
        // // 点击触发
        // this.graph.on('node:click',({node}) => {
        //     this.selectProcedure(node)
        // })
        // // 选中/取消 node
        this.graph.on('node:selected', ({ node }) => {
            this.selectProcedure(node)
            this.highlightingEdges(node, true)
        })
        this.graph.on('node:unselected', ({ node }) => {
            this.highlightingEdges(node, false);
            this.removeToolTips();
        })
        this.graph.on('node:mouseenter', ({ cell }) => {
            cell.setZIndex(12);
            const { disabled } = this.props;
            if (disabled) {
                cell.removeTool('contextmenu')
            }
        })
        this.graph.on('node:mouseleave', ({ cell }) => {
            cell.setZIndex(10);
            this.removeToolTips();
        })
        // // 选中/取消 edge
        this.graph.on('edge:selected', ({ edge }) => {
            this.highlightingNodes(edge, true)
        })
        this.graph.on('edge:unselected', ({ edge }) => {
            this.highlightingNodes(edge, false)
        })
        // link 移入/移出
        this.graph.on('edge:mouseenter', ({ cell }) => {
            cell.attr('lines/stroke', '#f8c1c1');
            const { selection, disabled } = this.props;
            if (selection && !disabled) {
                cell.addTools([
                    {
                        name: 'contextmenu',
                        args: new GraphEdge(cell.getProp(), true).getMenu()
                    }, {
                        name: 'target-arrowhead',
                        args: {
                            attrs: {
                                fill: '#ED7824',
                            },
                        },
                    }, {
                        name: 'source-arrowhead',
                        args: {
                            attrs: {
                                d: 'M 0, 0 m -7, 0 a 7,7 0 1,0 15,0 a 7,7 0 1,0 -15,0',
                                fill: '#ED7824',
                            },
                        },
                    }
                ])
            }
        })
        this.graph.on('edge:mouseleave', ({ cell }) => {
            cell.attr('lines/stroke', 'transparent');
            cell.removeTools();
        })

        // 点击空白部分
        this.graph.on('blank:click', (ev) => {
            this.removeToolTips();
            this.selectProcedure(null)
        })
    }
    selectHighlinghtNode = (id, center = false) => {  // 默认选中当前
        let nodes = this.graph.getNodes();
        let currentSelectNode = nodes.find(el => el.id === id);
        if (currentSelectNode) {
            this.highlightingEdges(currentSelectNode, true)
            this.highlinghtNode(currentSelectNode);
            if (center) { // 以当前cell为中心
                this.graph.centerCell(currentSelectNode)
            };
        }
    }
    highlinghtNode = (cell, nColor = '#FD8200', eColor = '#FD8200') => {  // 高亮
        if (cell.isNode()) {
            cell.setZIndex(12);
            cell.attr('body', {
                rx: 8,
                ry: 8,
                fill: nColor,
                filter: {
                    name: 'highlight',
                    args: {
                        color: nColor,
                        width: 3,
                        opacity: 1,
                    }
                },
            })
        } else {
            cell.setZIndex(5);
            cell.attr('line/stroke', eColor)
            cell.attr('line/stroke-width', 4)
            this.highlinghtLabel(cell, `active`, true);
        }
    }
    unHighlinghtNode = (cell) => {  // 取消高亮
        if (cell.isNode()) {
            cell.setZIndex(10);
            cell.attr('body', {
                fill: '#f5f5f5',
                filter: {
                    name: 'highlight',
                    args: {
                        color: '#f5f5f5',
                        width: 2,
                        opacity: 0,
                    }
                },
            })
        } else {
            cell.setZIndex(2);
            cell.attr('line/stroke', '#979797');
            cell.attr('line/stroke-width', 2);
            this.highlinghtLabel(cell, [`active`], false);
        }
    }
    highlinghtLabel = (cell, classList, flag) => {  // 高亮 label
        let markDom = document.getElementsByClassName(`mark-item-${cell.id}`)[0];
        if (markDom) {
            if (flag) {
                markDom.classList.add(classList);
            } else {
                markDom.classList.remove(...classList);
            }
        }
    }
    highlightingEdges = (node, flag) => { // 高亮Edges
        if (!node) return;
        let beforLink = this.graph.getIncomingEdges(node);
        let afterLink = this.graph.getOutgoingEdges(node);
        if (beforLink && beforLink.length) {
            beforLink.forEach(el => {
                if (flag) {
                    el.setZIndex(5);
                    this.highlinghtNode(el, '#2E6BE6', '#2E6BE6');
                    this.highlinghtLabel(el, `befor-class`, true);
                } else {
                    this.unHighlinghtNode(el);
                    this.highlinghtLabel(el, [`after-class`, `befor-class`], false);
                }
            })
        }
        if (afterLink && afterLink.length) {
            afterLink.forEach(el => {
                if (flag) {
                    el.setZIndex(5);
                    this.highlinghtNode(el, '#DE2AA2', '#DE2AA2');
                    this.highlinghtLabel(el, `after-class`, true);
                } else {
                    this.unHighlinghtNode(el);
                    this.highlinghtLabel(el, [`after-class`, `befor-class`], false);
                }
            })
        }
    }
    highlightingNodes = (node, flag) => {  // 高亮Nodes
        if (!node) return;
        let lighlinghtNodes = this.graph.getNeighbors(node);
        if (lighlinghtNodes && lighlinghtNodes.length) {
            lighlinghtNodes.forEach(el => {
                if (flag) {
                    this.highlinghtNode(el)
                } else {
                    this.unHighlinghtNode(el)
                }
            })
        }
    }
    createLable = (args) => {  // 创建配比置
        const item = args.edge.getProp()?.link;
        const { selectors } = args;
        const content = selectors.foContent;
        if (content) {
            const btn = document.createElement('div');
            let _multiplicity = item.multiplicity !== undefined ? item.multiplicity : 1;
            btn.className = `multiplicity-box mark-item-${item.id}`;
            btn.innerHTML = `<span id="multiplicity-item-${item.id}">${_multiplicity}</span>`;
            btn.addEventListener('dblclick', () => {
                const { clickMultiplicity } = this.props;
                if (typeof clickMultiplicity == 'function') {
                    clickMultiplicity(item)
                }
            })
            content.appendChild(btn)
        }
    }
    updataProcedureDom = (procedure) => {
        let currentDom = document.getElementsByClassName(`procedure-item-${procedure.id}`)[0];
        if (!currentDom) {
            return console.log('找不到元素!');
        }
        if (CraftOtype.isCraft(procedure)) {
            const title = `<div class="heydat_procedure_title">
                ${procedure.qc ? `<span class="is-qc">质</span>` : ``}
                ${procedure.completion ? `<span class="is-weight">权</span>` : ``}
				<span class="procedure-name" title=${procedure.name}>${procedure.name}</span>
			</div>`;
            const dataType = `<div class="heydat_procedure_datatype">
			   <div class="datatype_item pointer datatype_item_work" title=${procedure?.outputSchema?.dataType?.name}>生产：${procedure?.outputSchema?.dataType?.name || ''}</div>
				${procedure.qc ? `<div class="datatype_item pointer datatype_item_qc" title=${procedure?.qcSchema?.dataType?.name}>质检：${procedure?.qcSchema?.dataType?.name}</div>` : ``}
			</div>`;
            const status = `<div class="heydat_procedure_config">
				<div class="work-measure">${icon}<span class="measure-item">${procedure?.outputSchema?.measure || 0}</span><font>积分</font></div>
			</div>`;
            currentDom.innerHTML = `${title}${dataType}${status}`;
        } else {
            const otid = procedure?.type?.otid;
            const currentType = CraftOtype.getCurrentType(otid);
            let typeIcon = `<div class="heydat_svg_icon">
			<i class="svg_icon">${currentType?.iconSvg}</i>
			<i class="active">${currentType?.activeIconSvg}</i>
			</div>`;
            const typeName = `<div class="heydat_svg_name">${procedure.name}</div>`;
            let tipName = procedure?.outputSchema?.dataType?.name;
            if (CraftOtype.isCurrentType(otid, 3)) {
                tipName = procedure?.attributes?.dataCount || '0';
            }
            if (CraftOtype.isCurrentType(otid, 4)) {
                tipName = procedure?.attributes?.condition;
            }
            let templateHtml = tipName ? `<div class="heydat_procedure_datatype datatype_item_work" title=${tipName}><div class="datatype_item_work datatype_item pointer">${currentType.tipText}：${tipName}</div></div>` : '';
            if (CraftOtype.isCurrentType(otid, 7)) {
                let carffList = this.props?.nodes || this.craft?.dag?.nodes;
                let isEntry = procedure?.attributes?.isEntry;
                if (isEntry === true) {
                    typeIcon = `<div class="heydat_svg_icon">
                                    <i class="svg_icon">入</i>
                                    <i class="active">入</i>
                                </div>`;
                } else if (isEntry === false) {
                    typeIcon = `<div class="heydat_svg_icon">
                                    <i class="svg_icon">出</i>
                                    <i class="active">出</i>
                                </div>`;
                }
                if (procedure?.attributes?.isEntry) {
                    templateHtml = ``
                    // templateHtml = `<div class="heydat_procedure_datatype datatype_item_work" title=${tipName}><div class="datatype_item_work datatype_item pointer">${currentType.tipText}：${tipName}</div></div>`;
                } else {
                    tipName = procedure?.attributes?.linkedEntry;
                    let currentLinked = '';
                    if (carffList && carffList.length) {
                        currentLinked = carffList.find(el => el.id === tipName);
                    }
                    templateHtml = tipName ? `<div class="heydat_procedure_datatype datatype_item_work" title=${currentLinked ? currentLinked.name : tipName}><div class="datatype_item_work datatype_item pointer">${currentType.otherTipText}：${currentLinked ? currentLinked.name : tipName}</div></div>` : ``;
                }
            }
            currentDom.innerHTML = `${typeIcon}${typeName}${templateHtml}`;
        }
        return currentDom
    }
    initViewEventBus = () => {
        // 点击物料
        eventBus.on('selectDataType', dataType => {
            const { showDataType } = this.props;
            if (typeof showDataType == 'function') {
                showDataType(dataType)
            }
        })
        // 项目回滚
        eventBus.on('nodeMenuHandle', obj => {
            if (obj.key === '3') {
                // 回滚
                const { rollBackProcedure } = this.props;
                if (typeof rollBackProcedure == 'function') {
                    rollBackProcedure(obj);
                }
            } else if (obj.key === '4') {
                // 批量重做异常任务
                const { resetErrorTask } = this.props;
                if (typeof resetErrorTask == 'function') {
                    resetErrorTask(obj);
                }
            }
        })
    }
    showResult = (startTime) => {
        const duration = (new Date().getTime() - startTime) / 1000
        console.log('renderOver:' + duration + 's');
    }
    componentDidMount() {
        let startTime = new Date().getTime();
        const { dataInfo } = this.props;
        registerTools(); // 注册工具
        this.el = document.getElementById('craftview');
        this.graph = initGraph(this);
        this.loadCraft(dataInfo);
        // setTimeout(()=>{
        // this.loadCraft(dataInfo,false);
        // },5000)
        this.selectGraph();
        this.initViewEventBus(); // 初始化自定义监听事件
        this.cleanHistory(); // 初始化历史记录
        this.showResult(startTime)
        setTimeout(() => {
            this.resetView();  // 居中
        })
    }
    render() {
        return (
            <div style={{ display: "flex", height: "100%" }}>
                <div id="craftview" style={{ flex: 1 }}></div>
            </div>
        );
    }
}