import { find, first, forEach, get, includes, isEmpty, isEqual, map, merge, } from 'lodash';
import { BaseCell } from '../cell/base-cell';
import { CellType, EXTRA_COLUMN_FIELD, EXTRA_FIELD, S2Event, } from '../common/constant';
import { InteractionStateName } from '../common/constant/interaction';
import { GuiIcon } from '../common/icons';
import { includeCell } from '../utils/cell/data-cell';
import { getActionIconConfig, groupIconsByPosition, } from '../utils/cell/header-cell';
import { findFieldCondition } from '../utils/condition/condition';
import { renderIcon } from '../utils/g-renders';
import { getSortTypeIcon } from '../utils/sort-action';
export class HeaderCell extends BaseCell {
    getHeaderConfig() {
        return this.headerConfig || {};
    }
    isShallowRender() {
        return super.isShallowRender() || this.headerConfig.shallowRender;
    }
    shouldInit() {
        return super.shouldInit() && !this.isShallowRender();
    }
    handleRestOptions(...[headerConfig]) {
        this.headerConfig = Object.assign({}, headerConfig);
        const { value, query } = this.meta;
        const sortParams = this.spreadsheet.dataCfg.sortParams || [];
        // 该单元格是否为需要展示排序 icon 单元格
        const isSortCell = this.isSortCell();
        const sortParam = find([...sortParams].reverse(), (item) => isSortCell &&
            (item === null || item === void 0 ? void 0 : item.sortByMeasure) === value &&
            isEqual(get(item, 'query'), query));
        const type = getSortTypeIcon(sortParam, isSortCell);
        this.headerConfig.sortParam = Object.assign(Object.assign(Object.assign({}, this.headerConfig.sortParam), (sortParam || { query })), { type });
    }
    initCell() {
        this.resetTextAndConditionIconShapes();
        this.actionIcons = [];
        this.hasDefaultHiddenIcon = false;
        this.generateIconConfig();
    }
    generateIconConfig() {
        var _a, _b;
        this.conditionIconMappingResult = this.getIconConditionResult();
        const { sortParam } = this.getHeaderConfig();
        // 为什么有排序参数就不展示 actionIcon 了？背景不清楚，先照旧处理
        if (this.showSortIcon()) {
            this.actionIconConfig = {
                icons: [
                    {
                        name: (sortParam === null || sortParam === void 0 ? void 0 : sortParam.type) || 'none',
                        position: 'right',
                    },
                ],
                belongsCell: this
                    .cellType,
                isSortIcon: true,
            };
        }
        else {
            this.actionIconConfig = getActionIconConfig(this.spreadsheet.options.headerActionIcons, this.meta, this.cellType);
        }
        this.groupedIcons = groupIconsByPosition((_b = (_a = this.actionIconConfig) === null || _a === void 0 ? void 0 : _a.icons) !== null && _b !== void 0 ? _b : [], this.conditionIconMappingResult);
    }
    getFormattedFieldValue() {
        const { isTotalRoot, isGrandTotals, value } = this.meta;
        const formatter = this.spreadsheet.dataSet.getFieldFormatter(this.meta.field);
        /**
         * 如果是 table mode，列头不需要被格式化
         * 树状模式下，小计是父维度本身，需要被格式化，此时只有总计才不需要被格式化
         * 平铺模式下，总计/小计 文字单元格，不需要被格式化
         * 自定义树模式下，没有总计小计概念，isTotals 均为 false, 所以不受影响
         */
        let shouldFormat = true;
        if (this.spreadsheet.isTableMode()) {
            shouldFormat = false;
        }
        else if (this.spreadsheet.isHierarchyTreeType()) {
            shouldFormat = !(isGrandTotals && isTotalRoot);
        }
        else {
            shouldFormat = !isTotalRoot;
        }
        const formattedValue = shouldFormat && formatter
            ? formatter(value, undefined, this.meta)
            : value;
        return {
            formattedValue,
            value,
        };
    }
    shouldShowDefaultHeaderActionIcon() {
        return this.spreadsheet.options.showDefaultHeaderActionIcon;
    }
    showSortIcon() {
        const { dataCfg } = this.spreadsheet;
        const isEmptyValues = isEmpty(dataCfg.fields.values);
        if (this.shouldShowDefaultHeaderActionIcon() && !isEmptyValues) {
            const { sortParam } = this.getHeaderConfig();
            const query = this.meta.query;
            if (this.isShallowRender()) {
                return query;
            }
            // sortParam 的 query，和 type 本身可能会 undefined
            return (query &&
                isEqual(sortParam === null || sortParam === void 0 ? void 0 : sortParam.query, query) &&
                (sortParam === null || sortParam === void 0 ? void 0 : sortParam.type) &&
                (sortParam === null || sortParam === void 0 ? void 0 : sortParam.type) !== 'none');
        }
        return false;
    }
    getActionIconStyle(options) {
        const { icon } = this.getStyle();
        const conditionStyle = this.getTextConditionMappingResult();
        const defaultTextFill = (conditionStyle === null || conditionStyle === void 0 ? void 0 : conditionStyle.fill) || this.getTextStyle().fill;
        return {
            width: icon === null || icon === void 0 ? void 0 : icon.size,
            height: icon === null || icon === void 0 ? void 0 : icon.size,
            // 优先级: 单个 icon 颜色配置 > 全部 icon 颜色配置 > 主题 icon 颜色配置 > 文本默认颜色
            fill: options.fill === null
                ? undefined
                : (options === null || options === void 0 ? void 0 : options.fill) || (icon === null || icon === void 0 ? void 0 : icon.fill) || defaultTextFill,
            cursor: 'pointer',
        };
    }
    // 是否设置为默认隐藏 action icon，默认隐藏的交互为 hover 后可见
    hasDefaultHideActionIcon() {
        return this.hasDefaultHiddenIcon;
    }
    addActionIcon(options) {
        const { x, y, name, defaultHide, onClick, onHover, isSortIcon } = options;
        const icon = new GuiIcon(Object.assign(Object.assign({}, this.getActionIconStyle(options)), { name,
            x,
            y }));
        icon.toggleVisibility(!defaultHide);
        icon.addEventListener('mouseover', (event) => {
            this.spreadsheet.emit(S2Event.GLOBAL_ACTION_ICON_HOVER, event);
            onHover === null || onHover === void 0 ? void 0 : onHover({
                hovering: true,
                name,
                meta: this.meta,
                event,
            });
        });
        icon.addEventListener('mouseleave', (event) => {
            this.spreadsheet.emit(S2Event.GLOBAL_ACTION_ICON_HOVER_OFF, event);
            onHover === null || onHover === void 0 ? void 0 : onHover({
                hovering: false,
                name,
                meta: this.meta,
                event,
            });
        });
        icon.addEventListener('click', (event) => {
            this.spreadsheet.emit(S2Event.GLOBAL_ACTION_ICON_CLICK, event);
            if (isSortIcon) {
                this.spreadsheet.handleGroupSort(event, this.meta);
                return;
            }
            onClick === null || onClick === void 0 ? void 0 : onClick({
                name,
                meta: this.meta,
                event,
            });
        });
        this.actionIcons.push(icon);
        this.appendChild(icon);
    }
    drawActionAndConditionIcons({ updatePositionOnly = false, } = {}) {
        if (isEmpty(this.groupedIcons.left) && isEmpty(this.groupedIcons.right)) {
            return;
        }
        if (!this.leftIconPosition || !this.rightIconPosition) {
            return;
        }
        let updatePositionOnlyIndex = 0;
        forEach(this.groupedIcons, (icons, position) => {
            const { size, margin } = this.getStyle().icon;
            const iconMargin = position === 'left' ? margin.right : margin.right;
            const iconPosition = position === 'left' ? this.leftIconPosition : this.rightIconPosition;
            forEach(icons, (icon, i) => {
                var _a, _b, _c, _d;
                const x = iconPosition.x + (size + iconMargin) * i;
                const y = iconPosition.y;
                if (icon.isConditionIcon) {
                    const iconCfg = {
                        x,
                        y,
                        name: icon.name,
                        width: size,
                        height: size,
                        fill: icon.fill,
                    };
                    if (this.conditionIconShape) {
                        if (updatePositionOnly) {
                            this.conditionIconShape.updatePosition({ x, y });
                            return;
                        }
                        this.conditionIconShape.reRender(iconCfg);
                    }
                    else {
                        this.conditionIconShape = renderIcon(this, iconCfg);
                    }
                    this.addConditionIconShape(this.conditionIconShape);
                    return;
                }
                if (updatePositionOnly) {
                    (_a = this.actionIcons[updatePositionOnlyIndex++]) === null || _a === void 0 ? void 0 : _a.updatePosition({ x, y });
                    return;
                }
                const { onClick, onHover, defaultHide, isSortIcon } = this.actionIconConfig;
                const defaultHideHandler = (_b = icon.defaultHide) !== null && _b !== void 0 ? _b : defaultHide;
                const iconDefaultHide = typeof defaultHideHandler === 'function'
                    ? defaultHideHandler(this.meta, icon.name)
                    : defaultHideHandler;
                if (iconDefaultHide) {
                    this.hasDefaultHiddenIcon = true;
                }
                this.addActionIcon({
                    name: icon.name,
                    fill: icon.fill,
                    x,
                    y,
                    defaultHide: iconDefaultHide,
                    onClick: (_c = icon.onClick) !== null && _c !== void 0 ? _c : onClick,
                    onHover: (_d = icon.onHover) !== null && _d !== void 0 ? _d : onHover,
                    isSortIcon,
                });
            });
        });
    }
    isSortCell() {
        var _a, _b, _c;
        // 数值置于列头, 排序 icon 绘制在列头叶子节点; 置于行头, 排序 icon 绘制在行头叶子节点
        const isValueInCols = (_b = (_a = this.spreadsheet) === null || _a === void 0 ? void 0 : _a.isValueInCols) === null || _b === void 0 ? void 0 : _b.call(_a);
        const isMaxLevel = this.meta.level === ((_c = this.meta.hierarchy) === null || _c === void 0 ? void 0 : _c.maxLevel);
        if (isValueInCols) {
            return isMaxLevel && this.cellType === CellType.COL_CELL;
        }
        return isMaxLevel && this.cellType === CellType.ROW_CELL;
    }
    handleByStateName(cells, stateName) {
        if (includeCell(cells, this)) {
            this.updateByState(stateName);
        }
    }
    handleSearchResult(cells) {
        if (!includeCell(cells, this)) {
            return;
        }
        const targetCell = find(cells, (cell) => cell === null || cell === void 0 ? void 0 : cell['isTarget']);
        if (targetCell.id === this.getMeta().id) {
            this.updateByState(InteractionStateName.HIGHLIGHT);
        }
        else {
            this.updateByState(InteractionStateName.SEARCH_RESULT);
        }
    }
    handleHover(cells) {
        var _a;
        if (includeCell(cells, this)) {
            this.updateByState(InteractionStateName.HOVER);
            if (this.hasDefaultHideActionIcon()) {
                // hover 只会有一个 cell
                this.toggleActionIcon((_a = cells === null || cells === void 0 ? void 0 : cells[0]) === null || _a === void 0 ? void 0 : _a.id);
            }
        }
    }
    handleSelect(cells, nodes = []) {
        if (includeCell(cells, this)) {
            this.updateByState(InteractionStateName.SELECTED);
        }
        const selectedNodeIds = map(nodes, 'id');
        if (includes(selectedNodeIds, this.meta.id)) {
            this.updateByState(InteractionStateName.SELECTED);
        }
    }
    getTextStyle() {
        const textOverflowStyle = this.getCellTextWordWrapStyle();
        const { text, bolderText, measureText } = this.getStyle();
        let style;
        if (this.isMeasureField()) {
            style = measureText || text;
        }
        else if (this.isBolderText()) {
            style = bolderText;
        }
        else {
            style = text;
        }
        return this.getContainConditionMappingResultTextStyle(Object.assign(Object.assign({}, textOverflowStyle), style));
    }
    getBackgroundColor() {
        var _a;
        const { backgroundColor, backgroundColorOpacity } = ((_a = this.getStyle()) === null || _a === void 0 ? void 0 : _a.cell) || {};
        return merge({ backgroundColor, backgroundColorOpacity }, this.getBackgroundConditionFill());
    }
    toggleActionIcon(id) {
        if (this.getMeta().id === id) {
            const visibleActionIcons = [];
            forEach(this.actionIcons, (icon) => {
                // 仅存储当前不可见的 icon
                if (icon.parsedStyle.visibility !== 'visible') {
                    icon.toggleVisibility(true);
                    visibleActionIcons.push(icon);
                }
            });
            this.spreadsheet.store.set('visibleActionIcons', visibleActionIcons);
        }
    }
    getIconPosition() {
        return this.leftIconPosition || this.rightIconPosition;
    }
    getInteractedCells() {
        var _a;
        return (_a = this.spreadsheet.interaction) === null || _a === void 0 ? void 0 : _a.getCells([
            CellType.CORNER_CELL,
            CellType.COL_CELL,
            CellType.ROW_CELL,
            CellType.SERIES_NUMBER_CELL,
        ]);
    }
    update() {
        const { interaction } = this.spreadsheet;
        const stateInfo = interaction === null || interaction === void 0 ? void 0 : interaction.getState();
        if ((stateInfo === null || stateInfo === void 0 ? void 0 : stateInfo.stateName) === InteractionStateName.ALL_SELECTED) {
            this.updateByState(InteractionStateName.SELECTED);
            return;
        }
        const cells = this.getInteractedCells();
        if (!first(cells)) {
            return;
        }
        switch (stateInfo === null || stateInfo === void 0 ? void 0 : stateInfo.stateName) {
            case InteractionStateName.SELECTED:
            case InteractionStateName.ROW_CELL_BRUSH_SELECTED:
            case InteractionStateName.COL_CELL_BRUSH_SELECTED:
                this.handleSelect(cells, stateInfo === null || stateInfo === void 0 ? void 0 : stateInfo.nodes);
                break;
            case InteractionStateName.HOVER_FOCUS:
            case InteractionStateName.HOVER:
                this.handleHover(cells);
                break;
            case InteractionStateName.SEARCH_RESULT:
                this.handleSearchResult(cells);
                break;
            default:
                this.handleByStateName(cells, stateInfo === null || stateInfo === void 0 ? void 0 : stateInfo.stateName);
                break;
        }
    }
    updateByState(stateName) {
        super.updateByState(stateName, this);
    }
    hideInteractionShape() {
        super.hideInteractionShape();
    }
    isMeasureField() {
        return [EXTRA_FIELD, EXTRA_COLUMN_FIELD].includes(this.meta.field);
    }
    mappingValue(condition) {
        var _a;
        const value = this.getMeta().value;
        return (_a = condition.mapping) === null || _a === void 0 ? void 0 : _a.call(condition, value, this.meta, this);
    }
    findFieldCondition(conditions = []) {
        return findFieldCondition(conditions, this.meta.field);
    }
    getTreeIcon() {
        return this.treeIcon;
    }
    getActionIcons() {
        return this.actionIcons || [];
    }
    getMetaField() {
        return this.meta.field;
    }
    destroy() {
        this.meta.belongsCell = null;
        super.destroy();
    }
    reInitCell(node, headerConfig) {
        this.setMeta(node);
        this.handleRestOptions(headerConfig, undefined);
        this.initCell();
    }
    setHeaderConfig(headerConfig) {
        this.handleRestOptions(headerConfig, undefined);
        this.updateTextPosition();
        this.drawActionAndConditionIcons({ updatePositionOnly: true });
    }
}
//# sourceMappingURL=header-cell.js.map