import { getInstance, L10n } from '@syncfusion/ej2-base';
import { Ribbon as EJ2Ribbon, RibbonFileMenu, RibbonColorPicker, RibbonGallery, RibbonContextualTab, RibbonKeyTip, RibbonBackstage } from '@syncfusion/ej2-ribbon';
import { Dictionary } from '../../document-editor/base/index';
import { RibbonTabManager } from './ribbon-base/ribbon-tab-manager';
import { RibbonContextualTabManager } from './ribbon-base/ribbon-contextual-tab-manager';
import { RibbonStateManager } from './ribbon-base/ribbon-state-manager';
import { RibbonEventManager } from './ribbon-base/ribbon-event-manager';
import { RibbonHelper } from '../helper/ribbon-helper';
import { ComboBox } from '@syncfusion/ej2-dropdowns';
/**
 * Ribbon class for DocumentEditorContainer
 */
var Ribbon = /** @class */ (function () {
    /**
     * Constructor for the Ribbon class
     * @param {DocumentEditorContainer} container - Specifies the document editor container
     * @private
     */
    function Ribbon(container) {
        /**
         * @private
         */
        this.numericTextBoxCollection = new Dictionary();
        /**
         * @private
         */
        this.previousContext = '';
        this.container = container;
        this.localObj = new L10n('documenteditorcontainer', this.container.defaultLocale, this.container.locale);
    }
    Object.defineProperty(Ribbon.prototype, "documentEditor", {
        /**
         * Gets the document editor instance
         * @private
         * @returns {DocumentEditor} The document editor instance
         */
        get: function () {
            return this.container.documentEditor;
        },
        enumerable: true,
        configurable: true
    });
    /**
     * Gets the module name
     * @returns {string} Module name
     * @private
     */
    Ribbon.prototype.getModuleName = function () {
        return 'ribbon';
    };
    /**
     * Initializes the ribbon component
     * @returns {void}
     * @private
     */
    Ribbon.prototype.initializeRibbon = function () {
        this.tabManager = new RibbonTabManager(this.container, this.localObj);
        this.contextualTabManager = new RibbonContextualTabManager(this.container);
        this.stateManager = new RibbonStateManager(this.container);
        this.eventManager = new RibbonEventManager(this, this.container);
        this.initializeInternal();
    };
    Ribbon.prototype.initializeInternal = function () {
        if (!this.container.ribbonContainer) {
            return;
        }
        this.createRibbonElement();
        this.renderRibbon();
        if (this.tabManager.homeTab) {
            this.tabManager.homeTab.updateStyleGallery();
        }
    };
    Ribbon.prototype.createRibbonElement = function () {
        this.ribbonElement = document.createElement('div');
        this.ribbonElement.id = this.container.element.id + '_document-editor-ribbon';
        this.ribbonElement.classList.add('e-de-ribbon');
        if (this.container.enableRtl) {
            this.ribbonElement.classList.add('e-rtl');
        }
        // Append ribbon to toolbar container
        this.container.ribbonContainer.appendChild(this.ribbonElement);
    };
    Ribbon.prototype.renderRibbon = function () {
        var _this = this;
        var tabs = this.tabManager.getRibbonTabs();
        var fileMenuItems = this.tabManager.getFileMenuItems();
        var contextualTabs = this.contextualTabManager.getContextualTabs();
        EJ2Ribbon.Inject(RibbonFileMenu, RibbonColorPicker, RibbonGallery, RibbonContextualTab, RibbonKeyTip);
        this.ribbon = new EJ2Ribbon({
            tabs: tabs,
            selectedTab: 0,
            enableRtl: this.container.enableRtl,
            locale: this.container.locale,
            contextualTabs: contextualTabs,
            launcherIconClick: this.eventManager.onLauncherIconClicked.bind(this.eventManager),
            enableKeyTips: true,
            activeLayout: this.container.ribbonLayout,
            tabSelected: this.eventManager.onTabSelected.bind(this.eventManager),
            ribbonCollapsing: this.eventManager.onCollapse.bind(this.eventManager),
            ribbonExpanding: this.eventManager.onExpand.bind(this.eventManager),
            ribbonLayoutSwitched: this.eventManager.onRibbonLayoutChange.bind(this.eventManager),
            created: function () {
                var fontSizeElement = document.getElementById(_this.container.element.id + '_ribbon_font_size');
                if (fontSizeElement) {
                    var fontSizeInstance = getInstance(fontSizeElement, ComboBox);
                    fontSizeInstance.allowCustom = true;
                }
            }
        });
        this.ribbon.isAngular = this.container.isModalDialog;
        // Check if backstage menu is configured
        if (this.backstageMenu) {
            EJ2Ribbon.Inject(RibbonBackstage);
            this.ribbon.backStageMenu = this.backstageMenu;
            this.ribbon.fileMenu = {
                visible: false
            };
        }
        else {
            // Use traditional file menu
            this.ribbon.fileMenu = {
                text: this.localObj.getConstant('File'),
                menuItems: fileMenuItems,
                keyTip: 'F',
                visible: true,
                select: this.eventManager.onFileMenuItemSelect.bind(this.eventManager)
            };
        }
        this.ribbon.appendTo(this.ribbonElement);
    };
    /**
     * Adds a new tab to the ribbon UI.
     * @param {RibbonTabModel} tab - The ribbon tab model to add.
     * @param {string | RibbonTabType} insertBefore - Specifies the existing tab ID or type before which the new tab will be inserted.
     * If not specified, the new tab will be inserted at the end of the ribbon.
     * @returns {void}
     * @public
     */
    Ribbon.prototype.addTab = function (tab, insertBefore) {
        if (insertBefore !== undefined) {
            this.ribbon.addTab(tab, RibbonHelper.getTabId(insertBefore, this.container.element.id));
        }
        else {
            this.ribbon.addTab(tab);
        }
    };
    /**
     * Adds a new item to an existing group in the ribbon.
     * @param {RibbonGroupInfo} groupId - The information about the group to add the item to.
     * @param {RibbonItemModel} item - The ribbon item model to add.
     * @param {string | number} insertBefore - Specifies the existing item ID or index before which the new item will be inserted.
     * If a string is provided, it's treated as an item ID. If a number is provided, it's treated as an item index.
     * If not specified, the new item will be inserted at the end of the group.
     * @returns {void}
     * @public
     */
    Ribbon.prototype.addItem = function (groupId, item, insertBefore) {
        if (insertBefore !== undefined) {
            if (typeof insertBefore === 'string') {
                var collectionId = RibbonHelper.getCollectionIdFromItem(groupId, this.container, insertBefore);
                this.ribbon.addItem(collectionId, item, insertBefore);
            }
            else {
                var targetInfo = { tabId: groupId.tabId, groupIndex: groupId.index, itemIndexes: [insertBefore] };
                var itemIds = RibbonHelper.getItemIdsFromGroup(targetInfo, this.container);
                this.ribbon.addItem(RibbonHelper.getCollectionIdFromItem(groupId, this.container), item, itemIds[0]);
            }
        }
        else {
            this.ribbon.addItem(RibbonHelper.getCollectionIdFromItem(groupId, this.container), item);
        }
    };
    /**
     * Adds a new group to an existing tab in the ribbon.
     * @param {string | RibbonTabType} tabId - The ID or type of the tab to add the group to.
     * @param {RibbonGroupModel} group - The ribbon group model to add.
     * @param {number} insertBefore - Specifies the existing group index before which the new group will be inserted. If not specified, the new group will be inserted at the end.
     * @returns {void}
     * @public
     */
    Ribbon.prototype.addGroup = function (tabId, group, insertBefore) {
        if (insertBefore !== undefined) {
            this.ribbon.addGroup(RibbonHelper.getTabId(tabId, this.container.element.id), group, RibbonHelper.getGroupId({ tabId: tabId, index: insertBefore }, this.ribbon.tabs, this.container.element.id));
        }
        else {
            this.ribbon.addGroup(RibbonHelper.getTabId(tabId, this.container.element.id), group);
        }
    };
    /**
     * Shows or hides a specific tab in the ribbon.
     * @param {string | RibbonTabType} tabId - The ID or type of the tab to show or hide.
     * @param {boolean} show - Whether to show (true) or hide (false) the tab.
     * @returns {void}
     * @public
     */
    Ribbon.prototype.showTab = function (tabId, show) {
        // Convert RibbonTabType to tab ID
        var ribbonTabId = RibbonHelper.getTabId(tabId, this.container.element.id);
        if (ribbonTabId === '') {
            return;
        }
        if (show) {
            this.ribbon.showTab(ribbonTabId);
        }
        else {
            this.ribbon.hideTab(ribbonTabId);
        }
    };
    /**
     * Shows or hides a specific group in a tab.
     * @param {string | RibbonGroupInfo} groupId - The ID of the group or group info to show or hide.
     * @param {boolean} show - Whether to show (true) or hide (false) the group.
     * @returns {void}
     * @public
     */
    Ribbon.prototype.showGroup = function (groupId, show) {
        var ribbonGroupId = RibbonHelper.getGroupId(groupId, this.ribbon.tabs, this.container.element.id);
        if (ribbonGroupId === '') {
            return;
        }
        if (show) {
            this.ribbon.showGroup(ribbonGroupId);
        }
        else {
            this.ribbon.hideGroup(ribbonGroupId);
        }
    };
    /**
     * Shows or hides specific items in the ribbon.
     * @param {string | RibbonItemInfo} itemId - The ID of the item or item information object to show or hide.
     * If a string is provided, it's treated as an item ID. If a RibbonItemInfo object is provided,
     * it will show/hide items based on the specified tab, group, and item indexes.
     * @param {boolean} show - Whether to show (true) or hide (false) the item(s).
     * @returns {void}
     * @public
     */
    Ribbon.prototype.showItems = function (itemId, show) {
        if (typeof itemId === 'string') {
            this.showItemInternal(itemId, show);
        }
        else {
            var itemIds = RibbonHelper.getItemIdsFromGroup(itemId, this.container);
            for (var _i = 0, itemIds_1 = itemIds; _i < itemIds_1.length; _i++) {
                var id = itemIds_1[_i];
                this.showItemInternal(id, show);
            }
        }
    };
    Ribbon.prototype.showItemInternal = function (itemId, show) {
        if (show) {
            this.ribbon.showItem(itemId);
        }
        else {
            this.ribbon.hideItem(itemId);
        }
    };
    /**
     * Enables or disables specific items in the ribbon.
     * @param {string | RibbonItemInfo} itemId - The ID of the item or item information object to show or hide.
     * If a string is provided, it's treated as an item ID. If a RibbonItemInfo object is provided,
     * it will enable/disable items based on the specified tab, group, and item indexes.
     * @param {boolean} enable - Whether to enable (true) or disable (false) the items.
     * @returns {void}
     * @public
     */
    Ribbon.prototype.enableItems = function (itemId, enable) {
        if (typeof itemId === 'string') {
            this.enableItemInternal(itemId, enable);
        }
        else {
            var itemIds = RibbonHelper.getItemIdsFromGroup(itemId, this.container);
            for (var _i = 0, itemIds_2 = itemIds; _i < itemIds_2.length; _i++) {
                var id = itemIds_2[_i];
                this.enableItemInternal(id, enable);
            }
        }
    };
    Ribbon.prototype.enableItemInternal = function (itemId, enable) {
        if (enable) {
            this.ribbon.enableItem(itemId);
        }
        else {
            this.ribbon.disableItem(itemId);
        }
    };
    /**
     * Update ribbon state based on current selection
     * @returns {void}
     * @private
     */
    Ribbon.prototype.updateRibbonState = function () {
        if (!this.ribbon) {
            return;
        }
        this.stateManager.updateRibbonState(this.ribbon);
        this.updateContextualTab();
        this.tabManager.updateAllTabs();
    };
    /**
     * Updates the contextual tab based on the current selection context
     * @returns {void}
     * @private
     */
    Ribbon.prototype.updateContextualTab = function () {
        var currentContext = this.documentEditor.selectionModule.contextType;
        var isInHeaderFooter = currentContext.indexOf('Header') >= 0
            || currentContext.indexOf('Footer') >= 0;
        if (isInHeaderFooter || currentContext.indexOf('Image') >= 0 || currentContext.indexOf('Table') >= 0 && currentContext.indexOf('TableOfContents') === -1) {
            this.contextualTabManager.updateContextualTabs(this.ribbon);
        }
        else {
            this.contextualTabManager.hideContextualTab(this.ribbon);
        }
        this.previousContext = currentContext;
    };
    /**
     * Updates the zoom button state when zoom factor changes
     * @returns {void}
     * @private
     */
    Ribbon.prototype.onZoomFactorChange = function () {
        this.tabManager.viewTab.zoomGroup.updateZoomButtonState();
    };
    /**
     * Refresh the ribbon
     * @returns {void}
     * @private
     */
    Ribbon.prototype.refresh = function () {
        if (this.ribbon) {
            this.ribbon.refresh();
            this.updateRibbonState();
        }
    };
    /**
     * @returns {void}
     * @private
     */
    Ribbon.prototype.onContentChange = function () {
        this.onRibbonContentChange();
    };
    /**
     * @returns {void}
     * @private
     */
    Ribbon.prototype.onDocumentChange = function () {
        this.onRibbonDocumentChange();
    };
    /**
     * @param {boolean} isToggle - toggle track changes.
     * @returns {void}
     * @private
     */
    Ribbon.prototype.initialize = function (isToggle) {
        if (this.container.backstageMenu) {
            this.backstageMenu = this.container.backstageMenu;
        }
        this.initializeRibbon();
        if (isToggle) {
            this.container.destroyPane();
            this.updateRibbonState();
            if (this.tabManager && this.tabManager.homeTab) {
                this.tabManager.homeTab.updateContentChanged();
            }
        }
    };
    /**
     * @param {boolean} restrictEditing - Whether to restrict editing or not
     * @returns {void}
     * @private
     */
    Ribbon.prototype.restrictEditingToggleHelper = function (restrictEditing) {
        this.enableDisableRibbonItem(!restrictEditing);
    };
    Ribbon.prototype.onRibbonContentChange = function () {
        // Handle content changes
        this.tabManager.homeTab.updateContentChanged();
        this.contextualTabManager.setContentChangeFlag(true);
        this.contextualTabManager.updateContextualTabs(this.ribbon);
        this.contextualTabManager.setContentChangeFlag(false);
    };
    /**
     * @param {boolean} enable - Emable/Disable insert comment toolbar item.
     * @returns {void}
     * @private
     */
    Ribbon.prototype.enableDisableInsertComment = function (enable) {
        if (this.tabManager.insertTab && this.tabManager.insertTab.commentsGroup) {
            this.tabManager.insertTab.commentsGroup.enableDisableComment(enable);
        }
        if (this.tabManager.reviewTab && this.tabManager.reviewTab.reviewCommentsGroup) {
            this.tabManager.reviewTab.reviewCommentsGroup.enableDisableCommentGroup(enable);
        }
    };
    Ribbon.prototype.onRibbonDocumentChange = function () {
        this.tabManager.homeTab.updateContentChanged();
        this.tabManager.updateStyleGallery();
        this.contextualTabManager.setContentChangeFlag(false);
        this.contextualTabManager.updateContextualTabs(this.ribbon);
    };
    /**
     * Enable or disable ribbon items based on protection state
     * @param {boolean} enable - Whether to enable or disable items
     * @returns {void}
     * @private
     */
    Ribbon.prototype.enableDisableRibbonItem = function (enable) {
        this.stateManager.enableDisableRibbonItem(this.ribbon, enable);
    };
    /**
     * @returns {void}
     * @private
     */
    Ribbon.prototype.toggleTrackChanges = function () {
        if (this.tabManager.reviewTab && this.tabManager.reviewTab.trackingGroup) {
            this.tabManager.reviewTab.trackingGroup.updateSelection();
        }
    };
    /**
     * Destroy the ribbon instance
     * @returns {void}
     * @private
     */
    Ribbon.prototype.destroy = function () {
        if (this.tabManager) {
            this.tabManager.destroy();
            this.tabManager = null;
        }
        if (this.ribbon) {
            this.ribbon.destroy();
            this.ribbon = null;
        }
        if (this.ribbonElement && this.ribbonElement.parentNode) {
            this.ribbonElement.parentNode.removeChild(this.ribbonElement);
        }
        if (this.container.ribbonContainer) {
            this.container.containerTarget.removeChild(this.container.ribbonContainer);
            this.container.ribbonContainer = undefined;
        }
        this.ribbonElement = null;
    };
    return Ribbon;
}());
export { Ribbon };
