var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
import G6 from '@antv/g6';
import { isEqual, isFunction, isObject, isString, omit } from '@antv/util';
import { useEffect, useRef } from 'react';
import { createNode } from '../utils/create-node';
import { createToolbar, Menu } from '../plugins';
import { bindDefaultEvents, bindSourceMapCollapseEvents, bindStateEvents, deepClone, getAnchorPoints, getArrowCfg, getCommonConfig, getGraphId, getGraphSize, getLevelData, getMarkerPosition, processMinimap, renderGraph, setTag, bindRadialExplore, getCenterNode, } from '../utils';
import { setGlobalInstance } from '../utils/global';
export default function useGraph(graphClass, config, extra) {
    if (extra === void 0) { extra = {}; }
    var container = useRef(null);
    var graphRef = useRef();
    var graphOptions = useRef();
    // data 单独处理，会被 G6 修改
    var graphData = useRef();
    var data = config.data, width = config.width, height = config.height, layout = config.layout, minimapCfg = config.minimapCfg, behaviors = config.behaviors, fitCenter = config.fitCenter, nodeCfg = config.nodeCfg, edgeCfg = config.edgeCfg, markerCfg = config.markerCfg, level = config.level, toolbarCfg = config.toolbarCfg, customLayout = config.customLayout;
    var graph = graphRef.current;
    /** 隐藏孤立边 */
    var setEdgesState = function (edges) {
        edges.forEach(function (edge) {
            var _a, _b;
            var _c = edge.getModel(), source = _c.source, target = _c.target;
            var sourceVisible = (_a = graph === null || graph === void 0 ? void 0 : graph.findById(source)) === null || _a === void 0 ? void 0 : _a.get('visible');
            var targetVisible = (_b = graph === null || graph === void 0 ? void 0 : graph.findById(target)) === null || _b === void 0 ? void 0 : _b.get('visible');
            if (sourceVisible === false || targetVisible === false) {
                edge.changeVisibility(false);
            }
        });
    };
    var changeData = function () {
        var _a;
        if (!graph) {
            return;
        }
        var currentData = data;
        if (level) {
            currentData = setTag(data);
        }
        graph.changeData(level ? getLevelData(currentData, level) : data);
        (_a = graph.get('eventData')) === null || _a === void 0 ? void 0 : _a.setData(currentData);
        setEdgesState(graph.getEdges());
        if (fitCenter) {
            graph.fitCenter();
        }
    };
    var updateLayout = function () {
        graph === null || graph === void 0 ? void 0 : graph.updateLayout(layout);
        if (fitCenter) {
            graph === null || graph === void 0 ? void 0 : graph.fitCenter();
        }
    };
    var updateNodes = function () {
        if (!graph) {
            return;
        }
        var _a = nodeCfg !== null && nodeCfg !== void 0 ? nodeCfg : {}, nodeType = _a.type, nodeAnchorPoints = _a.anchorPoints, nodeStyle = _a.style, nodeLabelCfg = _a.title;
        graph.getNodes().forEach(function (node) {
            var anchorPoints = getAnchorPoints(nodeAnchorPoints, node.getModel());
            graph.updateItem(node, {
                nodeCfg: nodeCfg,
                markerCfg: markerCfg,
                type: nodeType,
                style: nodeStyle,
                anchorPoints: anchorPoints,
                labelCfg: nodeLabelCfg,
            });
        });
    };
    var updateEdges = function () {
        if (!graph) {
            return;
        }
        var _a = edgeCfg !== null && edgeCfg !== void 0 ? edgeCfg : {}, edgeType = _a.type, edgeStyle = _a.style, startArrowCfg = _a.startArrow, endArrowCfg = _a.endArrow, labelCfg = _a.label;
        graph.getEdges().forEach(function (edge) {
            // 资金流向图&来源去向图
            if (['fund-line', 'labels-line'].includes(edgeType)) {
                graph.updateItem(edge, {
                    edgeCfg: edgeCfg,
                });
            }
            else {
                var edgeCfgModel = edge.getModel();
                var startArrow = getArrowCfg(startArrowCfg, edgeCfgModel);
                var endArrow = getArrowCfg(endArrowCfg, edgeCfgModel);
                var _a = labelCfg !== null && labelCfg !== void 0 ? labelCfg : {}, style = _a.style, content = _a.content;
                graph.updateItem(edge, {
                    type: edgeType,
                    label: getCommonConfig(content, edgeCfgModel, graph),
                    labelCfg: {
                        style: getCommonConfig(style, edgeCfgModel, graph),
                    },
                    style: __assign({ stroke: '#ccc', startArrow: startArrow, endArrow: endArrow }, (typeof edgeStyle === 'function' ? edgeStyle(edgeCfgModel, graph) : edgeStyle)),
                });
            }
        });
    };
    // 目前仅支持更新位置
    var updateMarker = function () {
        if (!graph) {
            return;
        }
        graph.getNodes().forEach(function (node) {
            var _a = (typeof markerCfg === 'function' ? markerCfg(node.getModel(), node.get('group')) : markerCfg).position, position = _a === void 0 ? 'right' : _a;
            var _b = node.getBBox(), width = _b.width, height = _b.height;
            var markerShape = node
                .get('group')
                .get('children')
                .find(function (item) { return item.get('name') === 'collapse-icon'; });
            if (markerShape) {
                markerShape === null || markerShape === void 0 ? void 0 : markerShape.attr(__assign({}, getMarkerPosition(position, [width, height])));
            }
        });
    };
    var getEdgeStateStyles = function (edgeStateStyles) {
        var _a = extra.name, name = _a === void 0 ? '' : _a;
        if (name !== 'FundFlowGraph') {
            return edgeStateStyles;
        }
        if (!edgeStateStyles) {
            return;
        }
        var _b = edgeStateStyles.hover, hover = _b === void 0 ? {} : _b;
        var endArrow = hover.endArrow, startArrow = hover.startArrow;
        if (!endArrow && !startArrow) {
            return edgeStateStyles;
        }
        return {
            hover: __assign(__assign({}, hover), { endArrow: endArrow ? getArrowCfg(endArrow) : false, startArrow: startArrow ? getArrowCfg(startArrow) : false }),
        };
    };
    useEffect(function () {
        var _a;
        if (graph && !graph.destroyed) {
            if (isEqual(data, graphData.current)) {
                return;
            }
            if (extra.name === 'RadialGraph' && !((_a = graphData.current.nodes) === null || _a === void 0 ? void 0 : _a.length)) {
                var centerNode = getCenterNode(data);
                graph.set('centerNode', centerNode);
                graph.updateLayout(__assign(__assign({}, layout), { focusNode: centerNode }));
            }
            else {
                changeData();
            }
            graphData.current = deepClone(data);
        }
    }, [data]);
    useEffect(function () {
        var _a, _b, _c, _d, _e;
        if (graph && !graph.destroyed) {
            if (isEqual(config, graphOptions.current)) {
                return;
            }
            if (!customLayout && !isEqual(layout, (_a = graphOptions.current) === null || _a === void 0 ? void 0 : _a.layout)) {
                updateLayout();
            }
            if (!isEqual(minimapCfg, (_b = graphOptions.current) === null || _b === void 0 ? void 0 : _b.minimapCfg)) {
                processMinimap(minimapCfg, graph);
            }
            if (!isEqual(nodeCfg, (_c = graphOptions.current) === null || _c === void 0 ? void 0 : _c.nodeCfg)) {
                updateNodes();
            }
            if (!isEqual(edgeCfg, (_d = graphOptions.current) === null || _d === void 0 ? void 0 : _d.edgeCfg)) {
                updateEdges();
            }
            if (!isEqual(markerCfg, (_e = graphOptions.current) === null || _e === void 0 ? void 0 : _e.markerCfg)) {
                updateMarker();
            }
            graphOptions.current = config;
        }
    }, [config]);
    useEffect(function () {
        if (graph && !graph.destroyed) {
            var graphSize = getGraphSize(width, height, container);
            graph.changeSize(graphSize[0], graphSize[1]);
        }
    }, [container, width, height]);
    useEffect(function () {
        if (graph && !graph.destroyed) {
            var defaultMode = graph.get('modes').default;
            var removingBehaviors_1 = [];
            defaultMode.forEach(function (be) {
                if (isObject(be)) {
                    removingBehaviors_1.push(be.type);
                }
                else if (isString(be)) {
                    removingBehaviors_1.push(be);
                }
            });
            graph.removeBehaviors(removingBehaviors_1, 'default');
            graph.addBehaviors(behaviors, 'default');
        }
    }, [behaviors]);
    useEffect(function () {
        if (container.current && graphClass) {
            var _a = extra.name, name_1 = _a === void 0 ? '' : _a;
            var graphSize = getGraphSize(width, height, container);
            var plugins = [];
            var nodeCfg_1 = config.nodeCfg, edgeCfg_1 = config.edgeCfg, behaviors_1 = config.behaviors, layout_1 = config.layout, animate = config.animate, autoFit = config.autoFit, fitCenter_1 = config.fitCenter, onReady = config.onReady, tooltipCfg = config.tooltipCfg, customLayout_1 = config.customLayout, menuCfg = config.menuCfg, fetchLoading = config.fetchLoading;
            var _b = nodeCfg_1 !== null && nodeCfg_1 !== void 0 ? nodeCfg_1 : {}, nodeType_1 = _b.type, nodeAnchorPoints_1 = _b.anchorPoints, nodeStateStyles = _b.nodeStateStyles, nodeStyle_1 = _b.style, nodeLabelCfg_1 = _b.title, linkCenter = _b.linkCenter, getChildren = _b.getChildren, asyncData = _b.asyncData;
            var _c = edgeCfg_1 !== null && edgeCfg_1 !== void 0 ? edgeCfg_1 : {}, edgeType = _c.type, edgeStyle_1 = _c.style, startArrowCfg_1 = _c.startArrow, endArrowCfg_1 = _c.endArrow, labelCfg_1 = _c.label, edgeStateStyles = _c.edgeStateStyles;
            // tooltip
            if (tooltipCfg && isFunction(tooltipCfg.customContent)) {
                var customContent_1 = tooltipCfg.customContent, rest = __rest(tooltipCfg, ["customContent"]);
                var tooltipPlugin = new G6.Tooltip(__assign(__assign({ offsetX: 10, offsetY: 20, itemTypes: ['node'] }, rest), { getContent: function (e) {
                        return createNode(customContent_1(e.item.getModel()), 'g6-tooltip');
                    } }));
                plugins.push(tooltipPlugin);
            }
            // menu
            if (menuCfg && isFunction(menuCfg.customContent)) {
                var menuPlugin = new Menu(__assign({ offsetX: 16 + 10, offsetY: 0, itemTypes: ['node'] }, menuCfg));
                plugins.push(menuPlugin);
            }
            graphRef.current = new G6[graphClass]({
                container: container.current,
                width: graphSize[0],
                height: graphSize[1],
                animate: animate,
                linkCenter: linkCenter,
                modes: {
                    default: behaviors_1,
                },
                defaultNode: __assign(__assign({}, nodeCfg_1), { nodeCfg: nodeCfg_1 }),
                defaultEdge: __assign(__assign({}, omit(edgeCfg_1, ['label'])), { edgeCfg: edgeCfg_1, labelCfg: labelCfg_1 === null || labelCfg_1 === void 0 ? void 0 : labelCfg_1.style }),
                nodeStateStyles: nodeStateStyles,
                edgeStateStyles: getEdgeStateStyles(edgeStateStyles),
                layout: customLayout_1 ? undefined : layout_1,
                fitView: autoFit,
                fitCenter: fitCenter_1,
                plugins: plugins,
            });
            var graphId_1 = getGraphId(graphRef.current);
            var graph_1 = graphRef.current;
            graph_1.set('id', graphId_1);
            setGlobalInstance(graphId_1, graph_1);
            var getLabel_1 = function (value) {
                // 辐射树图
                if (isString(value)) {
                    return value;
                }
                if (name_1 === 'FundFlowGraph') {
                    return value === null || value === void 0 ? void 0 : value.text;
                }
                return value === null || value === void 0 ? void 0 : value.title;
            };
            var customNode_1 = ['fund-card', 'indicator-card'];
            // defaultNode 默认只能绑定 plainObject，针对 Function 类型需要通过该模式绑定
            graph_1.node(function (node) {
                if (customNode_1.includes(nodeType_1) || name_1 === 'OrganizationGraph') {
                    var anchorPoints = getAnchorPoints(nodeAnchorPoints_1, node);
                    node.markerCfg = markerCfg;
                    return {
                        anchorPoints: anchorPoints,
                        _graphId: graphId_1,
                    };
                }
                var style = (nodeLabelCfg_1 !== null && nodeLabelCfg_1 !== void 0 ? nodeLabelCfg_1 : {}).style;
                return {
                    _graphId: graphId_1,
                    label: getLabel_1(node.value),
                    labelCfg: {
                        style: getCommonConfig(style, node, graph_1),
                    },
                    style: __assign({ stroke: '#ccc' }, (typeof nodeStyle_1 === 'function' ? nodeStyle_1(node, graph_1) : nodeStyle_1)),
                };
            });
            var getEdgeLabel_1 = function (edge) {
                var content = (labelCfg_1 !== null && labelCfg_1 !== void 0 ? labelCfg_1 : {}).content;
                if (['DecompositionTreeGraph', 'OrganizationGraph', 'RadialTreeGraph'].includes(name_1)) {
                    return getCommonConfig(content, edge, graph_1);
                }
                if (['FundFlowGraph', 'FlowAnalysisGraph'].includes(name_1)) {
                    var value = edge.value;
                    // @ts-ignore
                    return typeof value === 'object' ? value === null || value === void 0 ? void 0 : value.text : value;
                }
                return edge.value;
            };
            if (!['fund-line', 'labels-line'].includes(edgeType)) {
                graph_1.edge(function (edge) {
                    var startArrow = getArrowCfg(startArrowCfg_1, edge);
                    var endArrow = getArrowCfg(endArrowCfg_1, edge);
                    var style = (labelCfg_1 !== null && labelCfg_1 !== void 0 ? labelCfg_1 : {}).style;
                    return {
                        label: getEdgeLabel_1(edge),
                        labelCfg: {
                            style: getCommonConfig(style, edge, graph_1),
                        },
                        style: __assign({ stroke: '#ccc', startArrow: startArrow, endArrow: endArrow }, (typeof edgeStyle_1 === 'function' ? edgeStyle_1(edge, graph_1) : edgeStyle_1)),
                    };
                });
            }
            processMinimap(minimapCfg, graph_1);
            bindStateEvents(graph_1, config);
            if (markerCfg) {
                var sourceGraph = ['FlowAnalysisGraph', 'FundFlowGraph'];
                sourceGraph.includes(name_1)
                    ? bindSourceMapCollapseEvents(graph_1, asyncData, fetchLoading)
                    : bindDefaultEvents(graph_1, level, getChildren, fetchLoading);
            }
            if (name_1 === 'RadialGraph') {
                var centerNode = getCenterNode(data);
                graph_1.set('centerNode', centerNode);
                bindRadialExplore(graph_1, asyncData, layout_1, fetchLoading);
            }
            renderGraph(graph_1, data, level);
            if (fitCenter_1) {
                graph_1.fitCenter();
            }
            if (onReady) {
                onReady(graph_1);
            }
            graphData.current = deepClone(data);
        }
    }, []);
    useEffect(function () {
        if (graphRef.current && toolbarCfg) {
            createToolbar({ graph: graphRef.current, container: container.current, toolbarCfg: toolbarCfg });
        }
    }, [graphRef, toolbarCfg]);
    useEffect(function () {
        return function () {
            if ((graph === null || graph === void 0 ? void 0 : graph.current) && !graph.current.destroyed) {
                graph.current.destroy();
            }
        };
    }, []);
    return {
        container: container,
    };
}
