"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SlickColumnPicker = void 0;
const binding_1 = require("@slickgrid-universal/binding");
const utils_1 = require("@slickgrid-universal/utils");
const extensionCommonUtils_js_1 = require("../extensions/extensionCommonUtils.js");
const index_js_1 = require("../core/index.js");
/**
 * A control to add a Column Picker (right+click on any column header to reveal the column picker)
 * To specify a custom button in a column header, extend the column definition like so:
 *   this.gridOptions = {
 *     enableColumnPicker: true,
 *     columnPicker: {
 *       ... column picker options ...
 *     }
 *   }];
 * @class ColumnPickerControl
 * @constructor
 */
class SlickColumnPicker {
    /** Constructor of the SlickGrid 3rd party plugin, it can optionally receive options */
    constructor(extensionUtility, pubSubService, sharedService) {
        this.extensionUtility = extensionUtility;
        this.pubSubService = pubSubService;
        this.sharedService = sharedService;
        this._areVisibleColumnDifferent = false;
        this._columns = [];
        this._gridUid = '';
        this._menuElm = null;
        this._columnCheckboxes = [];
        this._defaults = {
            // the last 2 checkboxes titles
            hideForceFitButton: false,
            hideSyncResizeButton: false,
            forceFitTitle: 'Force fit columns',
            minHeight: 150,
            syncResizeTitle: 'Synchronous resize',
            headerColumnValueExtractor: (columnDef) => {
                return (0, utils_1.getHtmlStringOutput)(columnDef.columnPickerLabel || columnDef.name || '', 'innerHTML');
            },
        };
        this._bindEventService = new binding_1.BindingEventService();
        this.onColumnsChanged = new index_js_1.SlickEvent('onColumnsChanged');
        this._eventHandler = new index_js_1.SlickEventHandler();
        this._columns = this.sharedService.allColumns ?? [];
        this._gridUid = this.grid?.getUID?.() ?? '';
        this.init();
    }
    get addonOptions() {
        return this.gridOptions.columnPicker || {};
    }
    get eventHandler() {
        return this._eventHandler;
    }
    get columns() {
        return this._columns;
    }
    set columns(newColumns) {
        this._columns = newColumns;
    }
    get gridOptions() {
        return this.sharedService.gridOptions ?? {};
    }
    get grid() {
        return this.sharedService.slickGrid;
    }
    get menuElement() {
        return this._menuElm;
    }
    /** Initialize plugin. */
    init() {
        this._gridUid = this.grid.getUID() ?? '';
        this.gridOptions.columnPicker = { ...this._defaults, ...this.gridOptions.columnPicker };
        // add PubSub instance to all SlickEvent
        this.onColumnsChanged.setPubSubService(this.pubSubService);
        // localization support for the picker
        this.addonOptions.columnTitle = this.extensionUtility.getPickerTitleOutputString('columnTitle', 'columnPicker');
        this.addonOptions.forceFitTitle = this.extensionUtility.getPickerTitleOutputString('forceFitTitle', 'columnPicker');
        this.addonOptions.syncResizeTitle = this.extensionUtility.getPickerTitleOutputString('syncResizeTitle', 'columnPicker');
        this._eventHandler.subscribe(this.grid.onPreHeaderContextMenu, (e) => {
            if (['slick-column-name', 'slick-header-column'].some((className) => e.target?.classList.contains(className))) {
                this.handleHeaderContextMenu(e); // open picker only when preheader has column groups
            }
        });
        this._eventHandler.subscribe(this.grid.onHeaderContextMenu, this.handleHeaderContextMenu.bind(this));
        this._eventHandler.subscribe(this.grid.onColumnsReordered, extensionCommonUtils_js_1.updateColumnPickerOrder.bind(this));
        this._eventHandler.subscribe(this.grid.onClick, this.disposeMenu.bind(this));
        // Hide the menu on outside click.
        this._bindEventService.bind(document.body, 'mousedown', this.handleBodyMouseDown.bind(this), undefined, 'body');
        // destroy the picker if user leaves the page
        this._bindEventService.bind(document.body, 'beforeunload', this.dispose.bind(this), undefined, 'body');
    }
    /** Dispose (destroy) the SlickGrid 3rd party plugin */
    dispose() {
        this._eventHandler.unsubscribeAll();
        this._bindEventService.unbindAll();
        this.disposeMenu();
    }
    disposeMenu() {
        this._bindEventService.unbindAll('parent-menu');
        this._listElm?.remove();
        this._menuElm?.remove();
        this._menuElm = null;
    }
    createPickerMenu() {
        const menuElm = (0, utils_1.createDomElement)('div', {
            ariaExpanded: 'true',
            className: `slick-column-picker ${this._gridUid}`,
            role: 'menu',
        });
        extensionCommonUtils_js_1.updateColumnPickerOrder.call(this);
        // add Close button and optiona a Column list title
        extensionCommonUtils_js_1.addColumnTitleElementWhenDefined.call(this, menuElm);
        extensionCommonUtils_js_1.addCloseButtomElement.call(this, menuElm);
        this._listElm = (0, utils_1.createDomElement)('div', { className: 'slick-column-picker-list', role: 'menu' });
        this._bindEventService.bind(menuElm, 'click', extensionCommonUtils_js_1.handleColumnPickerItemClick.bind(this), undefined, 'parent-menu');
        document.body.appendChild(menuElm);
        return menuElm;
    }
    /**
     * Get all columns including hidden columns.
     * @returns {Array<Object>} - all columns array
     */
    getAllColumns() {
        return this._columns;
    }
    /**
     * Get only the visible columns.
     * @returns {Array<Object>} - all columns array
     */
    getVisibleColumns() {
        return this.grid.getColumns();
    }
    /** Translate the Column Picker headers and also the last 2 checkboxes */
    translateColumnPicker() {
        // update the properties by pointers, that is the only way to get Column Picker Control to see the new values
        if (this.addonOptions) {
            this.addonOptions.columnTitle = '';
            this.addonOptions.forceFitTitle = '';
            this.addonOptions.syncResizeTitle = '';
            this.addonOptions.columnTitle = this.extensionUtility.getPickerTitleOutputString('columnTitle', 'columnPicker');
            this.addonOptions.forceFitTitle = this.extensionUtility.getPickerTitleOutputString('forceFitTitle', 'columnPicker');
            this.addonOptions.syncResizeTitle = this.extensionUtility.getPickerTitleOutputString('syncResizeTitle', 'columnPicker');
        }
        // translate all columns (including hidden columns)
        this.extensionUtility.translateItems(this._columns, 'nameKey', 'name');
        // update the Titles of each sections (command, commandTitle, ...)
        this.translateTitleLabels(this.addonOptions);
    }
    // --
    // protected functions
    // ------------------
    /** Mouse down handler when clicking anywhere in the DOM body */
    handleBodyMouseDown(e) {
        // prettier-ignore
        if ((this._menuElm !== e.target && !this._menuElm?.contains(e.target)) || (e.target.className === 'close' && e.target.closest('.slick-column-picker'))) {
            this.disposeMenu();
        }
    }
    /** Mouse header context handler when doing a right+click on any of the header column title */
    handleHeaderContextMenu(e) {
        e.preventDefault();
        (0, utils_1.emptyElement)(this._menuElm);
        this._columnCheckboxes = [];
        this._menuElm = this.createPickerMenu();
        // add dark mode CSS class when enabled
        if (this.gridOptions.darkMode) {
            this._menuElm.classList.add('slick-dark-mode');
        }
        // load the column & create column picker list
        extensionCommonUtils_js_1.populateColumnPicker.call(this, this.addonOptions);
        document.body.appendChild(this._menuElm);
        this.repositionMenu(e);
    }
    repositionMenu(event) {
        const targetEvent = event?.touches?.[0] ?? event;
        if (this._menuElm) {
            // auto-positioned menu left/right by available viewport space
            const gridPos = this.grid.getGridPosition();
            const menuWidth = this._menuElm.clientWidth || 0;
            let menuOffsetLeft = targetEvent.pageX || 0;
            if (gridPos?.width && menuOffsetLeft + menuWidth >= gridPos.width) {
                menuOffsetLeft = menuOffsetLeft - menuWidth;
            }
            this._menuElm.style.top = `${targetEvent.pageY - 10}px`;
            this._menuElm.style.left = `${menuOffsetLeft}px`;
            this._menuElm.style.minHeight = (0, utils_1.findWidthOrDefault)(this.addonOptions.minHeight, '');
            this._menuElm.style.maxHeight = (0, utils_1.findWidthOrDefault)(this.addonOptions.maxHeight, `${window.innerHeight - targetEvent.clientY}px`);
            this._menuElm.style.display = 'block';
            this._menuElm.ariaExpanded = 'true';
            this._menuElm.appendChild(this._listElm);
        }
    }
    /** Update the Titles of each sections (command, commandTitle, ...) */
    translateTitleLabels(pickerOptions) {
        if (pickerOptions) {
            pickerOptions.columnTitle = this.extensionUtility.getPickerTitleOutputString('columnTitle', 'gridMenu');
        }
    }
}
exports.SlickColumnPicker = SlickColumnPicker;
//# sourceMappingURL=slickColumnPicker.js.map