import { find, get, merge } from 'lodash';
import { CellType, FrozenGroupArea, KEY_GROUP_ROW_RESIZE_AREA, ResizeAreaEffect, ResizeDirectionType, S2Event, } from '../common/constant';
import { CellBorderPosition, CellClipBox, } from '../common/interface';
import { CustomRect } from '../engine';
import { getHorizontalTextIconPosition, getVerticalIconPosition, } from '../utils/cell/cell';
import { renderCircle, renderTreeIcon } from '../utils/g-renders';
import { getAllChildrenNodeHeight } from '../utils/get-all-children-node-height';
import { getOrCreateResizeAreaGroupById, getResizeAreaAttrs, shouldAddResizeArea, } from '../utils/interaction/resize';
import { isMobile } from '../utils/is-mobile';
import { adjustTextIconPositionWhileScrolling } from './../utils/cell/text-scrolling';
import { normalizeTextAlign } from './../utils/normalize';
import { HeaderCell } from './header-cell';
export class RowCell extends HeaderCell {
    get cellType() {
        return CellType.ROW_CELL;
    }
    getBorderPositions() {
        return [CellBorderPosition.BOTTOM, CellBorderPosition.LEFT];
    }
    initCell() {
        super.initCell();
        // 绘制单元格背景
        this.drawBackgroundShape();
        // 绘制交互背景
        this.drawInteractiveBgShape();
        // 绘制交互边框
        this.drawInteractiveBorderShape();
        // 绘制单元格文本 or 图片
        this.drawTextOrCustomRenderer();
    }
    afterDrawText() {
        // 绘制字段和 action标记 -- icon 和 action
        this.drawActionAndConditionIcons();
        // 绘制树状模式收起展开的 icon
        this.drawTreeIcon();
        // 绘制树状模式下子节点层级占位圆点
        this.drawTreeLeafNodeAlignDot();
        // 绘制单元格边框
        this.drawBorders();
        // 绘制 resize 热区
        this.drawResizeAreaInLeaf();
        this.update();
    }
    getBackgroundColor() {
        const { backgroundColor, backgroundColorOpacity } = this.getCrossBackgroundColor(this.meta.rowIndex);
        return merge({ backgroundColor, backgroundColorOpacity }, this.getBackgroundConditionFill());
    }
    showTreeIcon() {
        return this.spreadsheet.isHierarchyTreeType() && !this.meta.isLeaf;
    }
    showTreeLeafNodeAlignDot() {
        var _a, _b;
        return (((_b = (_a = this.spreadsheet.options.style) === null || _a === void 0 ? void 0 : _a.rowCell) === null || _b === void 0 ? void 0 : _b.showTreeLeafNodeAlignDot) &&
            this.spreadsheet.isHierarchyTreeType());
    }
    // 获取树状模式下叶子节点的父节点收起展开 icon 图形属性
    getParentTreeIconCfg() {
        var _a, _b;
        if (!this.showTreeLeafNodeAlignDot() ||
            !this.spreadsheet.isHierarchyTreeType() ||
            !this.meta.isLeaf) {
            return;
        }
        const treeIcon = (_b = (_a = this.meta.parent) === null || _a === void 0 ? void 0 : _a.belongsCell) === null || _b === void 0 ? void 0 : _b.getTreeIcon();
        return treeIcon === null || treeIcon === void 0 ? void 0 : treeIcon.style;
    }
    onTreeIconClick() {
        const { isCollapsed, hierarchy } = this.meta;
        if (isMobile()) {
            return;
        }
        // 折叠行头时因 scrollY 没变，导致底层出现空白
        if (!isCollapsed) {
            const { scrollY: oldScrollY } = this.spreadsheet.facet.getScrollOffset();
            // 可视窗口高度
            const viewportHeight = this.spreadsheet.facet.panelBBox.viewportHeight || 0;
            // 被折叠项的高度
            const deleteHeight = getAllChildrenNodeHeight(this.meta);
            // 折叠后真实高度
            const realHeight = hierarchy.height - deleteHeight;
            if (oldScrollY > 0 && oldScrollY + viewportHeight > realHeight) {
                const currentScrollY = realHeight - viewportHeight;
                this.spreadsheet.facet.setScrollOffset({
                    scrollY: currentScrollY > 0 ? currentScrollY : 0,
                });
            }
        }
        this.emitCollapseEvent();
    }
    emitCollapseEvent() {
        this.spreadsheet.emit(S2Event.ROW_CELL_COLLAPSED__PRIVATE, {
            isCollapsed: !this.meta.isCollapsed,
            node: this.meta,
        });
    }
    drawTreeIcon() {
        if (!this.showTreeIcon()) {
            return;
        }
        const { isCollapsed } = this.meta;
        const { x } = this.getBBoxByType(CellClipBox.CONTENT_BOX);
        const { fill } = this.getTextStyle();
        const { size } = this.getStyle().icon;
        const contentIndent = this.getContentIndent();
        const iconX = x + contentIndent;
        const iconY = this.getIconPosition().y;
        this.treeIcon = renderTreeIcon({
            group: this,
            iconCfg: {
                x: iconX,
                y: iconY,
                width: size,
                height: size,
                fill,
            },
            isCollapsed,
            onClick: () => {
                this.onTreeIconClick();
            },
        });
        // 移动端, 点击热区为整个单元格
        if (isMobile()) {
            this.addEventListener('touchend', () => {
                this.emitCollapseEvent();
            });
        }
    }
    drawTreeLeafNodeAlignDot() {
        const parentTreeIconCfg = this.getParentTreeIconCfg();
        if (!parentTreeIconCfg) {
            return;
        }
        const { size, margin } = this.getStyle().icon;
        const x = parentTreeIconCfg.x + size + margin.right;
        const textY = this.getTextPosition().y;
        const { fill, fontSize } = this.getTextStyle();
        // 半径，暂时先写死，后面看是否有这个点点的定制需求
        const r = size / 5;
        this.treeLeafNodeAlignDot = renderCircle(this, {
            // 和收起展开 icon 保持居中对齐
            cx: x + size / 2,
            cy: textY + (fontSize - r) / 2,
            r,
            fill,
            // 暂时先写死，后面看是否有这个点点的定制需求
            fillOpacity: 0.3,
        });
    }
    isBolderText() {
        // 非叶子节点、小计总计，均为粗体
        const { isLeaf, isTotals, level } = this.meta;
        return (!isLeaf && level === 0) || isTotals;
    }
    getResizesArea() {
        return getOrCreateResizeAreaGroupById(this.spreadsheet, KEY_GROUP_ROW_RESIZE_AREA);
    }
    drawResizeAreaInLeaf() {
        if (!this.meta.isLeaf ||
            this.meta.hideRowCellVerticalResize ||
            !this.shouldDrawResizeAreaByType('rowCellVertical', this)) {
            return;
        }
        const { x, y, width, height } = this.getBBoxByType();
        const resizeStyle = this.getResizeAreaStyle();
        const resizeArea = this.getResizesArea();
        if (!resizeArea) {
            return;
        }
        const { position, width: headerWidth, viewportHeight: headerHeight, scrollX = 0, scrollY = 0, } = this.getHeaderConfig();
        const resizeAreaBBox = {
            x,
            y: y + height - resizeStyle.size,
            width,
            height: resizeStyle.size,
        };
        const isFrozen = this.meta.isFrozen;
        const frozenGroupAreas = this.spreadsheet.facet
            .frozenGroupAreas;
        const frozenRowGroup = frozenGroupAreas[FrozenGroupArea.Row];
        const frozenTrailingRowGroup = frozenGroupAreas[FrozenGroupArea.TrailingRow];
        const resizeClipAreaBBox = {
            x: 0,
            y: isFrozen ? 0 : frozenRowGroup.height,
            width: headerWidth,
            height: isFrozen
                ? Number.POSITIVE_INFINITY
                : headerHeight - frozenRowGroup.height - frozenTrailingRowGroup.height,
        };
        if (!shouldAddResizeArea(resizeAreaBBox, resizeClipAreaBBox, {
            scrollX,
            scrollY: isFrozen ? 0 : scrollY,
        })) {
            return;
        }
        const { offsetX, offsetY } = this.getHorizontalResizeAreaOffset();
        const resizeAreaWidth = this.spreadsheet.isFrozenRowHeader()
            ? headerWidth - position.x - (x - scrollX)
            : width;
        const attrs = getResizeAreaAttrs({
            theme: resizeStyle,
            type: ResizeDirectionType.Vertical,
            effect: ResizeAreaEffect.Cell,
            offsetX,
            offsetY,
            width,
            height,
            meta: this.meta,
            cell: this,
        });
        resizeArea.appendChild(new CustomRect({
            style: Object.assign(Object.assign({}, attrs.style), { x: offsetX, y: offsetY + height - resizeStyle.size, width: resizeAreaWidth }),
        }, attrs.appendInfo));
    }
    getHorizontalResizeAreaOffset() {
        const { position, viewportHeight: headerHeight, scrollX = 0, scrollY = 0, } = this.getHeaderConfig();
        const { x, y } = this.getBBoxByType();
        const frozenGroupAreas = this.spreadsheet.facet
            .frozenGroupAreas;
        const frozenRowGroup = frozenGroupAreas[FrozenGroupArea.Row];
        const frozenTrailingRowGroup = frozenGroupAreas[FrozenGroupArea.TrailingRow];
        const offsetX = position.x + x - scrollX;
        let offsetY = position.y;
        if (this.meta.isFrozenHead) {
            offsetY += y - frozenRowGroup.y;
        }
        else if (this.meta.isFrozenTrailing) {
            offsetY +=
                headerHeight -
                    frozenTrailingRowGroup.height +
                    y -
                    frozenTrailingRowGroup.y;
        }
        else {
            offsetY += y - scrollY;
        }
        return {
            offsetX,
            offsetY,
        };
    }
    getContentIndent() {
        if (!this.spreadsheet.isHierarchyTreeType()) {
            return 0;
        }
        const { icon, cell } = this.getStyle();
        const iconWidth = icon.size + icon.margin.right;
        let parent = this.meta.parent;
        let sum = 0;
        while (parent) {
            if (parent.height !== 0) {
                sum += iconWidth;
            }
            parent = parent.parent;
        }
        if (this.showTreeLeafNodeAlignDot()) {
            sum += this.isTreeLevel()
                ? 0
                : cell.padding.right + icon.margin.right;
        }
        return sum;
    }
    getTextIndent() {
        const { size, margin } = this.getStyle().icon;
        const contentIndent = this.getContentIndent();
        const treeIconWidth = this.showTreeIcon() ||
            (this.isTreeLevel() && this.showTreeLeafNodeAlignDot())
            ? size + margin.right
            : 0;
        return contentIndent + treeIconWidth;
    }
    // 判断当前节点的兄弟节点是否叶子节点
    isTreeLevel() {
        return find(get(this.meta, 'parent.children'), (cell) => !cell.isLeaf);
    }
    getMaxTextWidth() {
        const { width } = this.getBBoxByType(CellClipBox.CONTENT_BOX);
        return width - this.getTextIndent() - this.getActionAndConditionIconWidth();
    }
    getTextArea() {
        const content = this.getBBoxByType(CellClipBox.CONTENT_BOX);
        const textIndent = this.getTextIndent();
        return Object.assign(Object.assign({}, content), { x: content.x + textIndent, width: content.width - textIndent });
    }
    handleViewport() {
        if (this.meta.isFrozen) {
            return {
                start: 0,
                size: Number.POSITIVE_INFINITY,
            };
        }
        const { scrollY, viewportHeight } = this.getHeaderConfig();
        const frozenGroupAreas = this.spreadsheet.facet
            .frozenGroupAreas;
        const frozenRowGroupHeight = frozenGroupAreas[FrozenGroupArea.Row].height;
        const frozenTrailingRowGroupHeight = frozenGroupAreas[FrozenGroupArea.TrailingRow].height;
        const viewport = {
            start: scrollY + frozenRowGroupHeight,
            size: viewportHeight - frozenRowGroupHeight - frozenTrailingRowGroupHeight,
        };
        return viewport;
    }
    getContentPosition({ contentWidth = this.getActualTextWidth(), } = {}) {
        const textArea = this.getTextArea();
        const textStyle = this.getTextStyle();
        const { cell, icon: iconStyle } = this.getStyle();
        const viewport = this.handleViewport();
        const textHeight = this.getActualTextHeight();
        const { textStart } = adjustTextIconPositionWhileScrolling(viewport, {
            start: textArea.y,
            size: textArea.height,
        }, {
            align: normalizeTextAlign(textStyle.textBaseline),
            size: {
                textSize: textHeight,
            },
            padding: {
                start: cell.padding.top,
                end: cell.padding.bottom,
            },
        });
        const { textX, leftIconX, rightIconX } = getHorizontalTextIconPosition({
            bbox: textArea,
            textWidth: contentWidth,
            textAlign: textStyle.textAlign,
            groupedIcons: this.groupedIcons,
            iconStyle,
            isCustomRenderer: !!this.getRenderer(),
        });
        const iconY = getVerticalIconPosition(iconStyle === null || iconStyle === void 0 ? void 0 : iconStyle.size, textStart, textHeight, textStyle.textBaseline);
        this.leftIconPosition = {
            x: leftIconX,
            y: iconY,
        };
        this.rightIconPosition = {
            x: rightIconX,
            y: iconY,
        };
        return { x: textX, y: textStart };
    }
    getTextPosition() {
        return this.getContentPosition();
    }
    getResizedTextMaxLines() {
        var _a, _b, _c, _d, _e;
        const { rowCell } = this.spreadsheet.options.style;
        return ((_d = (_b = (_a = rowCell === null || rowCell === void 0 ? void 0 : rowCell.maxLinesByField) === null || _a === void 0 ? void 0 : _a[this.meta.id]) !== null && _b !== void 0 ? _b : (_c = rowCell === null || rowCell === void 0 ? void 0 : rowCell.maxLinesByField) === null || _c === void 0 ? void 0 : _c[this.meta.field]) !== null && _d !== void 0 ? _d : this.getMaxLinesByCustomHeight({
            isCustomHeight: (_e = this.meta.extra) === null || _e === void 0 ? void 0 : _e.isCustomHeight,
        }));
    }
    shouldShowDefaultHeaderActionIcon() {
        return (this.spreadsheet.options.showDefaultHeaderActionIcon &&
            !this.spreadsheet.isValueInCols());
    }
    setHeaderConfig(headerConfig) {
        super.setHeaderConfig(headerConfig);
    }
}
//# sourceMappingURL=row-cell.js.map