import { Container, Menu } from "./Menu";

import { cellInRange } from "../../../tools/helper";

import { TABLE_EVENT_TYPE } from "../../../core/TABLE_EVENT_TYPE";

const MENU_INSTANCE_FACTORY = {
    "dropdown-menu": function(table) {
        return new Menu(table);
    },
    "context-menu": function(table) {
        return new Menu(table);
    },
    container: table => new Container(table)
};

function getMenuInstanceInfo(table, col, row, type, dropDownMenuOptions) {
    var _a, _b, _c;
    if (-1 === col && -1 === row && "context-menu" === type) return (null == dropDownMenuOptions ? void 0 : dropDownMenuOptions.content) ? {
        type: type,
        position: dropDownMenuOptions.position,
        referencePosition: null !== (_a = dropDownMenuOptions.referencePosition) && void 0 !== _a ? _a : {
            rect: {
                left: 0,
                right: 0,
                top: 0,
                bottom: 0,
                width: 0,
                height: 0
            }
        },
        content: dropDownMenuOptions.content
    } : null;
    const {lineHeight: lineHeight, textBaseline: textBaseline, textStick: textStick} = table._getCellStyle(col, row);
    let rect = table.getCellRangeRelativeRect(table.getCellRange(col, row));
    textStick && (rect = table.getVisibleCellRangeRelativeRect({
        col: col,
        row: row
    }));
    let {left: left, right: right, bottom: bottom, top: top, width: width, height: height} = rect;
    if (table.isHeader(col, row) && ({left: left, right: right, bottom: bottom, top: top, width: width, height: height} = table.internalProps.headerHelper.getDropDownIconRect(rect, lineHeight, textBaseline || "middle")), 
    null == dropDownMenuOptions ? void 0 : dropDownMenuOptions.content) return {
        type: type,
        position: dropDownMenuOptions.position,
        referencePosition: null !== (_b = dropDownMenuOptions.referencePosition) && void 0 !== _b ? _b : {
            rect: {
                left: left,
                right: right,
                top: top,
                bottom: bottom,
                width: width,
                height: height
            }
        },
        content: dropDownMenuOptions.content
    };
    if ("dropdown-menu" === type) {
        let dropDownMenu = table.globalDropDownMenu;
        const headerData = table._getHeaderLayoutMap(col, row);
        dropDownMenu = null !== (_c = headerData.dropDownMenu) && void 0 !== _c ? _c : dropDownMenu;
        const pivotInfo = headerData.pivotInfo;
        return "function" == typeof dropDownMenu && (dropDownMenu = dropDownMenu({
            row: row,
            col: col,
            table: table
        })), {
            type: type,
            referencePosition: {
                rect: {
                    left: left,
                    right: right,
                    top: top,
                    bottom: bottom,
                    width: width,
                    height: height
                }
            },
            content: dropDownMenu,
            pivotInfo: pivotInfo
        };
    }
    return null;
}

export class MenuHandler {
    constructor(table) {
        this._table = table, this._menuInstances = {}, this._bindTableEvent(table);
    }
    release() {
        const menuInstances = this._menuInstances;
        for (const k in menuInstances) menuInstances[k].release();
        delete this._menuInstances, this._attachInfo = null;
    }
    _bindToCell(col, row, type, dropDownMenuOptions) {
        var _a;
        const info = this._attachInfo, instanceInfo = this._getMenuInstanceInfo(col, row, type, dropDownMenuOptions);
        if (!info || instanceInfo && info.instance === instanceInfo.instance || (null === (_a = info.instance) || void 0 === _a || _a.unbindMenuElement(), 
        this._attachInfo = null), !instanceInfo) return;
        const {instance: instance, info: menuInstanceInfo} = instanceInfo;
        if (instance && instance.bindMenuElement(col, row, menuInstanceInfo)) {
            const range = -1 === col && -1 === row ? {
                start: {
                    col: -1,
                    row: -1
                },
                end: {
                    col: -1,
                    row: -1
                }
            } : this._table.getCellRange(col, row);
            this._attachInfo = {
                range: range,
                instance: instance
            };
        }
    }
    _unbindFromCell() {
        const info = this._attachInfo;
        if (!info) return;
        const {instance: instance} = info;
        null == instance || instance.unbindMenuElement(), this._attachInfo = null;
    }
    _isBindToCell(col, row) {
        const info = this._attachInfo;
        return !!info && cellInRange(info.range, col, row);
    }
    pointInMenuElement(x, y) {
        if (!this._attachInfo) return !1;
        const info = this._attachInfo, {instance: instance} = info;
        return instance.pointInMenuElement(x, y);
    }
    _bindTableEvent(table) {
        table.on(TABLE_EVENT_TYPE.DROPDOWN_ICON_CLICK, (e => {
            this._attachInfo && this._isBindToCell(e.col, e.row) ? this._unbindFromCell() : this._bindToCell(e.col, e.row, "dropdown-menu");
        })), table.on(TABLE_EVENT_TYPE.DROPDOWN_MENU_CLEAR, (e => {
            this._unbindFromCell();
        })), table.on(TABLE_EVENT_TYPE.CONTEXTMENU_CELL, (e => {
            var _a, _b, _c, _d;
            if ("html" === (null === (_a = table.internalProps.menu) || void 0 === _a ? void 0 : _a.renderMode)) {
                const abstractPos = table._getMouseAbstractPoint(e.event);
                let menu = null;
                abstractPos.inTable && "function" == typeof (null === (_b = table.internalProps.menu) || void 0 === _b ? void 0 : _b.contextMenuItems) ? menu = table.internalProps.menu.contextMenuItems(table.getHeaderField(e.col, e.row), e.row, e.col, table) : abstractPos.inTable && Array.isArray(null === (_c = table.internalProps.menu) || void 0 === _c ? void 0 : _c.contextMenuItems) && (menu = null === (_d = table.internalProps.menu) || void 0 === _d ? void 0 : _d.contextMenuItems), 
                this._bindToCell(e.col, e.row, "context-menu", {
                    content: menu,
                    position: {
                        x: abstractPos.x,
                        y: abstractPos.y
                    }
                });
            }
        })), table.on(TABLE_EVENT_TYPE.CONTEXTMENU_CANVAS, (e => {
            var _a, _b, _c, _d;
            if ("html" === (null === (_a = table.internalProps.menu) || void 0 === _a ? void 0 : _a.renderMode)) {
                const abstractPos = table._getMouseAbstractPoint(e.event);
                let menu = null;
                abstractPos.inTable && "function" == typeof (null === (_b = table.internalProps.menu) || void 0 === _b ? void 0 : _b.contextMenuItems) ? menu = table.internalProps.menu.contextMenuItems(table.getHeaderField(e.col, e.row), e.row, e.col, table) : abstractPos.inTable && Array.isArray(null === (_c = table.internalProps.menu) || void 0 === _c ? void 0 : _c.contextMenuItems) && (menu = null === (_d = table.internalProps.menu) || void 0 === _d ? void 0 : _d.contextMenuItems), 
                this._bindToCell(-1, -1, "context-menu", {
                    content: menu,
                    position: {
                        x: abstractPos.x,
                        y: abstractPos.y
                    }
                });
            }
        }));
    }
    _getMenuInstanceInfo(col, row, type, dropDownMenuOptions) {
        const table = this._table, menuInstances = this._menuInstances, info = getMenuInstanceInfo(table, col, row, type, dropDownMenuOptions);
        if (!info) return null;
        return {
            instance: menuInstances && menuInstances[type] || menuInstances && (menuInstances[type] = MENU_INSTANCE_FACTORY[type](table)),
            type: type,
            info: info
        };
    }
    containElement(el) {
        var _a;
        for (const k in this._menuInstances) {
            if (null === (_a = this._menuInstances[k].getRootElement()) || void 0 === _a ? void 0 : _a.contains(el)) return !0;
        }
        return !1;
    }
}
//# sourceMappingURL=MenuHandler.js.map
