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);
};
import G6 from '@antv/g6';
import { clone, deepMix, each, isBoolean, isPlainObject, mix } from '@antv/util';
import { defaultCardStyle, defaultLabelStyle, defaultLineLabelStyle, defaultMargin } from '../../constants';
import { cloneBesidesImg, createMarker, getArrowCfg, getCssPadding, getStatusBBox, getStatusCfg, getStyle, setEllipsis, } from '../../utils';
import { getGlobalInstance } from '../../utils/global';
var getPathInfo = function (cfg) {
    var edgeCfg = cfg.edgeCfg;
    var startPoint = cfg.startPoint;
    var endPoint = cfg.endPoint;
    var startX = startPoint.x, startY = startPoint.y;
    var endX = endPoint.x, endY = endPoint.y;
    var yDiff = endY - startY;
    var useControlPoint = Math.abs(yDiff) > 0;
    var line1EndPoint;
    var line2StartPoint;
    var controlPoint;
    var path;
    if (Math.abs(yDiff) <= 5) {
        line2StartPoint = {
            x: startX + 20,
            y: endY,
        };
        path = [
            ['M', startX, startY],
            ['L', endX, endY],
        ];
    }
    else {
        var slope = useControlPoint ? Math.min(500 / Math.abs(yDiff), 20) : 0;
        var cpOffset = slope > 15 ? 0 : 16;
        var offset = yDiff < 0 ? cpOffset : -cpOffset;
        line1EndPoint = {
            x: startX + slope,
            y: endY + offset,
        };
        line2StartPoint = {
            x: line1EndPoint.x + cpOffset,
            y: endY,
        };
        // 控制点坐标
        controlPoint = {
            x: ((line1EndPoint.x - startX) * (endY - startY)) / (line1EndPoint.y - startY) + startX,
            y: endY,
        };
        path = [
            ['M', startX, startY],
            ['L', line1EndPoint.x, line1EndPoint.y],
            ['Q', controlPoint.x, controlPoint.y, line2StartPoint.x, line2StartPoint.y],
            ['L', endX, endY],
        ];
    }
    var _a = edgeCfg, startArrowCfg = _a.startArrow, endArrowCfg = _a.endArrow;
    var startArrow = getArrowCfg(startArrowCfg, cfg);
    var endArrow = getArrowCfg(endArrowCfg, cfg);
    return {
        startArrow: startArrow,
        endArrow: endArrow,
        path: path,
        line2StartPoint: line2StartPoint,
        endY: endY,
    };
};
var getPathText = function (value) {
    var text;
    var subText;
    if (value instanceof Object) {
        text = value.text;
        subText = value.subText;
    }
    else {
        text = value;
    }
    return { text: text, subText: subText };
};
// 通用指标卡
export var registerIndicatorGeometries = function () {
    var defaultTitleLabelStyle = {
        fill: '#fff',
        fontSize: 12,
    };
    var defaultTitleRectStyle = {
        fill: '#40a9ff',
        radius: [2, 2, 0, 0],
    };
    var defaultIconStyle = {
        width: 12,
        height: 12,
    };
    var ARROWS = ['startArrow', 'endArrow'];
    var SHAPE_DEFAULT_ATTRS = {
        lineWidth: 1,
        stroke: undefined,
        fill: undefined,
        lineAppendWidth: 1,
        opacity: undefined,
        strokeOpacity: undefined,
        fillOpacity: undefined,
        x: 0,
        y: 0,
        r: 10,
        width: 20,
        height: 20,
        shadowColor: undefined,
        shadowBlur: 0,
        shadowOffsetX: 0,
        shadowOffsetY: 0,
    };
    var PATH_SHAPE_DEFAULT_ATTRS = {
        lineWidth: 1,
        stroke: '#000',
        lineDash: undefined,
        startArrow: false,
        endArrow: false,
        opacity: undefined,
        strokeOpacity: undefined,
        fillOpacity: undefined,
        shadowColor: undefined,
        shadowBlur: 0,
        shadowOffsetX: 0,
        shadowOffsetY: 0,
    };
    var SHAPES_DEFAULT_ATTRS = {
        edge: PATH_SHAPE_DEFAULT_ATTRS,
        node: SHAPE_DEFAULT_ATTRS,
    };
    // 注册节点
    G6.registerNode('indicator-card', {
        // @ts-ignore
        draw: function (cfg, group) {
            var _a, _b, _c, _d;
            if (cfg === void 0) { cfg = {}; }
            var _e = cfg.value, value = _e === void 0 ? {} : _e, nodeCfg = cfg.nodeCfg, markerCfg = cfg.markerCfg;
            var _f = nodeCfg, titleCfg = _f.title, itemsCfg = _f.items, _g = _f.label, label = _g === void 0 ? {} : _g, style = _f.style, _h = _f.padding, padding = _h === void 0 ? 0 : _h, badge = _f.badge, autoWidth = _f.autoWidth, customContent = _f.customContent;
            var appendPadding = getStatusBBox(badge);
            var labelStyle = label.style;
            var cardPadding = getCssPadding(padding);
            var paddingArray = cardPadding.map(function (item, index) { return item + appendPadding[index]; });
            var _j = titleCfg !== null && titleCfg !== void 0 ? titleCfg : {}, titleStyle = _j.style, titleContainerStyle = _j.containerStyle, _k = _j.autoEllipsis, autoEllipsis = _k === void 0 ? true : _k;
            var _l = itemsCfg !== null && itemsCfg !== void 0 ? itemsCfg : {}, itemStyle = _l.style, itemContainerStyle = _l.containerStyle, layout = _l.layout, _m = _l.itemSpacing, itemSpacing = _m === void 0 ? 4 : _m, sort = _l.sort, _o = _l.padding, itemPadding = _o === void 0 ? [6, 0, 0] : _o;
            var itemPaddingArray = getCssPadding(itemPadding);
            var _p = value, title = _p.title, items = _p.items;
            var size = (cfg === null || cfg === void 0 ? void 0 : cfg.size) || [100, 30];
            if (typeof size === 'number')
                size = [size, size];
            var height = 0; // 统计容器总高度，动态设置
            var shapeWidth = size[0];
            var contentWidth = shapeWidth - paddingArray[1] - paddingArray[3];
            // card box
            var cardStyle = getStyle(style, cfg, group);
            var shape = group.addShape('rect', {
                attrs: __assign(__assign({ x: 0, y: 0, width: size[0], height: size[1] }, defaultCardStyle), cardStyle),
                name: 'main-box',
                draggable: true,
            });
            // node title
            var titleTextShape;
            var itemShape;
            var titleShape;
            if (title) {
                // title rect
                titleShape = group.addShape('rect', {
                    attrs: __assign(__assign({ x: 0, y: 0, width: size[0], height: 0 }, defaultTitleRectStyle), getStyle(titleContainerStyle, cfg, group)),
                    name: 'title-rect',
                    draggable: true,
                });
                var textStyle = __assign(__assign({}, defaultTitleLabelStyle), getStyle(titleStyle, cfg, group));
                titleTextShape = group.addShape('text', {
                    attrs: __assign({ x: paddingArray[3], y: paddingArray[0], textBaseline: 'top', text: autoEllipsis && !autoWidth ? setEllipsis(title, textStyle === null || textStyle === void 0 ? void 0 : textStyle.fontSize, contentWidth) : title }, textStyle),
                    name: 'title',
                });
                var titleHeight_1 = (titleTextShape ? titleTextShape.getBBox() : { height: size[1] / 2 }).height;
                titleShape === null || titleShape === void 0 ? void 0 : titleShape.attr('height', titleHeight_1 + paddingArray[0] + paddingArray[2]);
                height += titleShape.getBBox().height;
            }
            if (items) {
                if (!titleShape) {
                    height += paddingArray[0];
                }
                itemShape = group.addShape('rect', {
                    attrs: __assign({ x: paddingArray[3], y: height, width: contentWidth, height: 0 }, getStyle(itemContainerStyle, cfg, group)),
                    name: 'item-box',
                    draggable: true,
                });
                height += itemPaddingArray[0];
                var itemContentWidth_1 = contentWidth - itemPaddingArray[1] - itemPaddingArray[3];
                var isArray_1 = Array.isArray(items);
                var createRowItems_1 = function (item, contentWidth, startX, index) {
                    if (index === void 0) { index = 0; }
                    var rowHeight = [];
                    var valueShapeWidth = 0;
                    var keys = sort ? Object.keys(item) : ['text', 'value', 'icon'];
                    keys.forEach(function (key, keyIndex) {
                        var x;
                        var isIcon = key.startsWith('icon');
                        // sort 直接均分，简单化
                        if (sort || layout === 'flex') {
                            x = (keyIndex * contentWidth) / keys.length;
                        }
                        else if (layout === 'follow') {
                            x = valueShapeWidth;
                        }
                        else {
                            // layout === 'bundled'
                            // 直接均分，icon 紧随 value
                            x = key === 'text' ? 0 : contentWidth / 2;
                            x += isIcon ? valueShapeWidth : 0;
                        }
                        var keyShape = group.addShape(isIcon ? 'image' : 'text', {
                            attrs: __assign(__assign({ textBaseline: 'top', x: startX + x, y: height, text: item[key], img: item[key] }, (isIcon ? defaultIconStyle : defaultLabelStyle)), getStyle(itemStyle || labelStyle, cfg, group, key)),
                            name: "".concat(key, "-").concat(index, "-").concat(keyIndex),
                        });
                        if (key === 'value' || layout === 'follow') {
                            valueShapeWidth += keyShape.getBBox().width;
                            valueShapeWidth += layout === 'follow' ? itemSpacing : 0;
                        }
                        rowHeight.push(keyShape.getBBox().height);
                    });
                    return rowHeight;
                };
                var createItems_1 = function (item, index) {
                    var _a;
                    if (index === void 0) { index = 0; }
                    var itemsHeight = [];
                    if (customContent) {
                        itemsHeight.push((_a = customContent(item, group, {
                            startX: paddingArray[3] + itemPaddingArray[3],
                            startY: height,
                            width: itemContentWidth_1,
                        })) !== null && _a !== void 0 ? _a : 0);
                    }
                    else {
                        itemsHeight.push.apply(itemsHeight, createRowItems_1(item, itemContentWidth_1, paddingArray[3] + itemPaddingArray[3], index));
                    }
                    height += Math.max.apply(Math, itemsHeight);
                    if (isArray_1 && index !== items.length - 1) {
                        height += defaultMargin;
                    }
                };
                if (Array.isArray(items)) {
                    items.forEach(function (item, index) {
                        createItems_1(item, index);
                    });
                }
                else {
                    createItems_1(items);
                }
            }
            var titleHeight = (titleShape === null || titleShape === void 0 ? void 0 : titleShape.getBBox().height) || 0;
            itemShape === null || itemShape === void 0 ? void 0 : itemShape.attr('height', Math.max(height - titleHeight + itemPaddingArray[2], size[1]));
            var itemHeight = (itemShape === null || itemShape === void 0 ? void 0 : itemShape.getBBox().height) || 0;
            var shapeHeight = items
                ? (titleHeight || paddingArray[0]) + itemHeight + paddingArray[2]
                : titleHeight + itemHeight;
            shape === null || shape === void 0 ? void 0 : shape.attr('height', shapeHeight);
            if (autoWidth) {
                var shapeMaxX = Math.max.apply(null, (_a = group === null || group === void 0 ? void 0 : group.getChildren()) === null || _a === void 0 ? void 0 : _a.map(function (childrenShape) {
                    return childrenShape.getBBox().maxX || 0;
                }));
                var outerMaxX = Math.max(shapeWidth, shapeMaxX + paddingArray[1]);
                titleShape === null || titleShape === void 0 ? void 0 : titleShape.attr('width', outerMaxX);
                shape === null || shape === void 0 ? void 0 : shape.attr('width', outerMaxX);
                itemShape === null || itemShape === void 0 ? void 0 : itemShape.attr('width', shapeMaxX - paddingArray[1]);
            }
            if (badge) {
                var statusConfig = getStatusCfg(badge, [size[0], shapeHeight]);
                group.addShape('rect', {
                    attrs: __assign(__assign({ fill: '#40a9ff' }, statusConfig), getStyle(badge.style, cfg, group)),
                    name: 'status-rect',
                });
            }
            // collapse marker
            if (markerCfg) {
                var stateCollapsed = ((_c = (_b = group === null || group === void 0 ? void 0 : group.get('item')) === null || _b === void 0 ? void 0 : _b.getModel()) !== null && _c !== void 0 ? _c : {}).collapsed;
                var _q = shape.getBBox(), shapeWidth_1 = _q.width, shapeHeight_1 = _q.height;
                var _r = typeof markerCfg === 'function'
                    ? markerCfg(__assign(__assign({}, cfg), { graphData: __assign({}, (_d = getGlobalInstance(cfg._graphId)) === null || _d === void 0 ? void 0 : _d.get('eventData').getData()) }), group)
                    : markerCfg, show = _r.show, _s = _r.position, position = _s === void 0 ? 'right' : _s, collapsed = _r.collapsed, markerStyle = _r.style;
                createMarker({
                    show: show,
                    position: position,
                    collapsed: stateCollapsed !== null && stateCollapsed !== void 0 ? stateCollapsed : collapsed,
                    style: markerStyle,
                }, group, [shapeWidth_1, shapeHeight_1]);
                shape.attr('defaultCollapsed', collapsed);
            }
            return shape;
        },
        /**
         * 更新节点，包含文本
         * @override
         * @param  {Object} cfg 节点的配置项
         * @param  {Node} node 节点
         */
        // @ts-ignore
        update: undefined,
        // @ts-ignore
        setState: function (name, value, item) {
            var _a, _b;
            var shape = item.get('keyShape');
            if (!shape || shape.destroyed)
                return;
            var type = item.getType();
            var stateName = isBoolean(value) ? name : "".concat(name, ":").concat(value);
            var itemStateStyle = item.getStateStyle(stateName);
            // const originStyle = item.getOriginStyle();
            // 不允许设置一个不存在的状态
            if (!itemStateStyle) {
                return;
            }
            // 要设置或取消的状态的样式
            // 当没有 state 状态时，默认使用 model.stateStyles 中的样式
            var styles = Object.assign({}, itemStateStyle);
            var group = item.getContainer();
            // 从图元素现有的样式中删除本次要取消的 states 中存在的属性值。使用对象检索更快
            var keptAttrs = { x: 1, y: 1, cx: 1, cy: 1 };
            if (value) {
                var _loop_1 = function (key) {
                    var _c;
                    var style = styles[key];
                    if (isPlainObject(style) && !ARROWS.includes(key)) {
                        var subShape = group.find(function (element) { return element.get('name') === key; });
                        if (subShape) {
                            subShape.attr(style);
                        }
                    }
                    else {
                        // 非纯对象，则认为是设置到 keyShape 上面的
                        shape.attr((_c = {},
                            _c[key] = style,
                            _c));
                    }
                };
                // style 为要设置的状态的样式
                for (var key in styles) {
                    _loop_1(key);
                }
            }
            else {
                // 所有生效的 state 的样式
                var enableStatesStyle = cloneBesidesImg(item.getCurrentStatesStyle());
                var model = item.getModel();
                // 原始样式
                var originStyle_1 = mix({}, model.style, cloneBesidesImg(item.getOriginStyle()));
                var keyShapeName_1 = shape.get('name');
                // cloning  shape.attr(), keys.forEach to avoid cloning the img attr, which leads to maximum clone heap #2383
                // const keyShapeStyles = clone(shape.attr())
                var shapeAttrs_1 = shape.attr();
                var keyShapeStyles_1 = {};
                Object.keys(shapeAttrs_1).forEach(function (key) {
                    if (key === 'img')
                        return;
                    var attr = shapeAttrs_1[key];
                    if (attr && typeof attr === 'object') {
                        keyShapeStyles_1[key] = clone(attr);
                    }
                    else {
                        keyShapeStyles_1[key] = attr;
                    }
                });
                // 已有样式 - 要取消的状态的样式
                var filtetDisableStatesStyle = {};
                var _loop_2 = function (p) {
                    var style = styles[p];
                    if (isPlainObject(style) && !ARROWS.includes(p)) {
                        var subShape_1 = group.find(function (element) { return element.get('name') === p; });
                        if (subShape_1) {
                            var subShapeStyles_1 = clone(subShape_1.attr());
                            each(style, function (v, key) {
                                if (p === keyShapeName_1 && keyShapeStyles_1[key] && !keptAttrs[key]) {
                                    delete keyShapeStyles_1[key];
                                    var value_1 = originStyle_1[p][key] || SHAPES_DEFAULT_ATTRS[type][key];
                                    shape.attr(key, value_1);
                                }
                                else if (subShapeStyles_1[key] || subShapeStyles_1[key] === 0) {
                                    delete subShapeStyles_1[key];
                                    var value_2 = originStyle_1[p][key] || SHAPES_DEFAULT_ATTRS[type][key];
                                    subShape_1.attr(key, value_2);
                                }
                            });
                            filtetDisableStatesStyle[p] = subShapeStyles_1;
                        }
                    }
                    else {
                        if (keyShapeStyles_1[p] && !keptAttrs[p]) {
                            delete keyShapeStyles_1[p];
                            var value_3 = originStyle_1[p] ||
                                (originStyle_1[keyShapeName_1] ? originStyle_1[keyShapeName_1][p] : undefined) ||
                                SHAPES_DEFAULT_ATTRS[type][p];
                            shape.attr(p, value_3);
                        }
                    }
                };
                // styles 为要取消的状态的样式
                for (var p in styles) {
                    _loop_2(p);
                }
                // 从图元素现有的样式中删除本次要取消的 states 中存在的属性值后，
                // 如果 keyShape 有 name 属性，则 filtetDisableStatesStyle 的格式为 { keyShapeName: {} }
                // 否则为普通对象
                if (!keyShapeName_1) {
                    mix(filtetDisableStatesStyle, keyShapeStyles_1);
                }
                else {
                    filtetDisableStatesStyle[keyShapeName_1] = keyShapeStyles_1;
                }
                for (var key in enableStatesStyle) {
                    if (keptAttrs[key])
                        continue;
                    var enableStyle = enableStatesStyle[key];
                    if (!isPlainObject(enableStyle) || ARROWS.includes(key)) {
                        // 把样式属性merge到keyShape中
                        if (!keyShapeName_1) {
                            mix(originStyle_1, (_a = {},
                                _a[key] = enableStyle,
                                _a));
                        }
                        else {
                            mix(originStyle_1[keyShapeName_1], (_b = {},
                                _b[key] = enableStyle,
                                _b));
                            delete originStyle_1[key];
                        }
                        delete enableStatesStyle[key];
                    }
                }
                var originstyles = {};
                deepMix(originstyles, originStyle_1, filtetDisableStatesStyle, enableStatesStyle);
                var keyShapeSetted = false;
                var _loop_3 = function (originKey) {
                    var _d;
                    var style = originstyles[originKey];
                    if (isPlainObject(style) && !ARROWS.includes(originKey)) {
                        var subShape = group.find(function (element) { return element.get('name') === originKey; });
                        if (subShape) {
                            if (originKey === keyShapeName_1) {
                                keyShapeSetted = true;
                            }
                            if (originKey !== 'collapse-icon')
                                subShape.attr(style);
                        }
                    }
                    else if (!keyShapeSetted) {
                        var value_4 = style || SHAPES_DEFAULT_ATTRS[type][originKey];
                        shape.attr((_d = {},
                            _d[originKey] = value_4,
                            _d));
                    }
                };
                for (var originKey in originstyles) {
                    _loop_3(originKey);
                }
            }
        },
    }, 'single-node');
    // 注册边
    G6.registerEdge('labels-line', {
        // @ts-ignore
        draw: function draw(cfg, group) {
            if (cfg === void 0) { cfg = {}; }
            var edgeCfg = cfg.edgeCfg, value = cfg.value;
            var _a = getPathText(value), text = _a.text, subText = _a.subText;
            var _b = edgeCfg, edgeStyle = _b.style, labelCfg = _b.label;
            var _c = getPathInfo(cfg), startArrow = _c.startArrow, endArrow = _c.endArrow, path = _c.path, line2StartPoint = _c.line2StartPoint, endY = _c.endY;
            var _d = labelCfg !== null && labelCfg !== void 0 ? labelCfg : {}, labelStyle = _d.style, _e = _d.margin, margin = _e === void 0 ? 4 : _e;
            var line = group.addShape('path', {
                attrs: __assign({ path: path, stroke: '#ccc', startArrow: startArrow, endArrow: endArrow }, (typeof edgeStyle === 'function' ? edgeStyle(cfg, group) : edgeStyle)),
                name: 'path-shape',
            });
            var createItem = function (itemText, key, attrs) {
                group.addShape('text', {
                    attrs: __assign({ text: itemText, x: line2StartPoint.x }, attrs),
                    name: "line-text-".concat(key),
                });
            };
            if (text) {
                var textStyle = __assign(__assign({}, defaultLineLabelStyle), getStyle(labelStyle, cfg, group, 'text'));
                var offsetY = subText ? Number(("".concat(textStyle.fontSize) || '12').replace(/px/g, '')) / 2 : 0;
                createItem(text, 'text', __assign({ y: endY - offsetY - margin / 2 }, textStyle));
            }
            if (subText) {
                var textStyle = __assign(__assign({}, defaultLineLabelStyle), getStyle(labelStyle, cfg, group, 'subText'));
                var offsetY = Number(("".concat(textStyle.fontSize) || '12').replace(/px/g, '')) / 2;
                createItem(text, 'subText', __assign({ y: endY + offsetY + margin / 2 }, textStyle));
            }
            return line;
        },
        // @ts-ignore
        update: function (cfg, edge) {
            var edgeCfg = cfg.edgeCfg, value = cfg.value;
            var _a = getPathText(value), text = _a.text, subText = _a.subText;
            var group = edge.getContainer();
            var getShape = function (shapeName) {
                return group.get('children').find(function (item) { return item.get('name') === shapeName; });
            };
            var _b = getPathInfo(cfg), startArrow = _b.startArrow, endArrow = _b.endArrow, path = _b.path, line2StartPoint = _b.line2StartPoint, endY = _b.endY;
            var _c = edgeCfg, edgeStyle = _c.style, labelCfg = _c.label;
            var _d = labelCfg !== null && labelCfg !== void 0 ? labelCfg : {}, labelStyle = _d.style, _e = _d.margin, margin = _e === void 0 ? 4 : _e;
            // path
            var pathShape = getShape('path-shape');
            pathShape === null || pathShape === void 0 ? void 0 : pathShape.attr(__assign({ path: path, stroke: '#ccc', startArrow: startArrow, endArrow: endArrow }, (typeof edgeStyle === 'function' ? edgeStyle(cfg, group) : edgeStyle)));
            // path text
            var texts = ['text', 'subText'];
            var hasSubText = !!getShape("line-text-subText");
            texts.forEach(function (key) {
                var textShape = getShape("line-text-".concat(key));
                var textStyle = __assign(__assign({}, defaultLineLabelStyle), getStyle(labelStyle, cfg, group, key));
                var offsetY = hasSubText ? Number(("".concat(textStyle.fontSize) || '12').replace(/px/g, '')) / 2 : 0;
                textShape === null || textShape === void 0 ? void 0 : textShape.attr(__assign({ x: line2StartPoint.x, y: key === 'text' ? endY - offsetY - margin / 2 : endY + offsetY + margin / 2, text: key === 'text' ? text : subText }, textStyle));
            });
        },
    }, 'single-edge');
};
