/**
 * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
/**
 * @module heading/headingui
 */
import { Plugin } from 'ckeditor5/src/core.js';
import { ViewModel, createDropdown, addListToDropdown, MenuBarMenuListItemView, MenuBarMenuListView, MenuBarMenuView, MenuBarMenuListItemButtonView } from 'ckeditor5/src/ui.js';
import { Collection } from 'ckeditor5/src/utils.js';
import { getLocalizedOptions } from './utils.js';
import '../theme/heading.css';
/**
 * The headings UI feature. It introduces the `headings` dropdown.
 */
export default class HeadingUI extends Plugin {
    /**
     * @inheritDoc
     */
    static get pluginName() {
        return 'HeadingUI';
    }
    /**
     * @inheritDoc
     */
    init() {
        const editor = this.editor;
        const t = editor.t;
        const options = getLocalizedOptions(editor);
        const defaultTitle = t('Choose heading');
        const accessibleLabel = t('Heading');
        // Register UI component.
        editor.ui.componentFactory.add('heading', locale => {
            const titles = {};
            const itemDefinitions = new Collection();
            const headingCommand = editor.commands.get('heading');
            const paragraphCommand = editor.commands.get('paragraph');
            const commands = [headingCommand];
            for (const option of options) {
                const def = {
                    type: 'button',
                    model: new ViewModel({
                        label: option.title,
                        class: option.class,
                        role: 'menuitemradio',
                        withText: true
                    })
                };
                if (option.model === 'paragraph') {
                    def.model.bind('isOn').to(paragraphCommand, 'value');
                    def.model.set('commandName', 'paragraph');
                    commands.push(paragraphCommand);
                }
                else {
                    def.model.bind('isOn').to(headingCommand, 'value', value => value === option.model);
                    def.model.set({
                        commandName: 'heading',
                        commandValue: option.model
                    });
                }
                // Add the option to the collection.
                itemDefinitions.add(def);
                titles[option.model] = option.title;
            }
            const dropdownView = createDropdown(locale);
            addListToDropdown(dropdownView, itemDefinitions, {
                ariaLabel: accessibleLabel,
                role: 'menu'
            });
            dropdownView.buttonView.set({
                ariaLabel: accessibleLabel,
                ariaLabelledBy: undefined,
                isOn: false,
                withText: true,
                tooltip: accessibleLabel
            });
            dropdownView.extendTemplate({
                attributes: {
                    class: [
                        'ck-heading-dropdown'
                    ]
                }
            });
            dropdownView.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled) => {
                return areEnabled.some(isEnabled => isEnabled);
            });
            dropdownView.buttonView.bind('label').to(headingCommand, 'value', paragraphCommand, 'value', (heading, paragraph) => {
                const whichModel = paragraph ? 'paragraph' : heading;
                if (typeof whichModel === 'boolean') {
                    return defaultTitle;
                }
                // If none of the commands is active, display default title.
                if (!titles[whichModel]) {
                    return defaultTitle;
                }
                return titles[whichModel];
            });
            dropdownView.buttonView.bind('ariaLabel').to(headingCommand, 'value', paragraphCommand, 'value', (heading, paragraph) => {
                const whichModel = paragraph ? 'paragraph' : heading;
                if (typeof whichModel === 'boolean') {
                    return accessibleLabel;
                }
                // If none of the commands is active, display default title.
                if (!titles[whichModel]) {
                    return accessibleLabel;
                }
                return `${titles[whichModel]}, ${accessibleLabel}`;
            });
            // Execute command when an item from the dropdown is selected.
            this.listenTo(dropdownView, 'execute', evt => {
                const { commandName, commandValue } = evt.source;
                editor.execute(commandName, commandValue ? { value: commandValue } : undefined);
                editor.editing.view.focus();
            });
            return dropdownView;
        });
        editor.ui.componentFactory.add('menuBar:heading', locale => {
            const menuView = new MenuBarMenuView(locale);
            const headingCommand = editor.commands.get('heading');
            const paragraphCommand = editor.commands.get('paragraph');
            const commands = [headingCommand];
            const listView = new MenuBarMenuListView(locale);
            menuView.set({
                class: 'ck-heading-dropdown'
            });
            listView.set({
                ariaLabel: t('Heading'),
                role: 'menu'
            });
            menuView.buttonView.set({
                label: t('Heading')
            });
            menuView.panelView.children.add(listView);
            for (const option of options) {
                const listItemView = new MenuBarMenuListItemView(locale, menuView);
                const buttonView = new MenuBarMenuListItemButtonView(locale);
                listItemView.children.add(buttonView);
                listView.items.add(listItemView);
                buttonView.set({
                    label: option.title,
                    role: 'menuitemradio',
                    class: option.class
                });
                buttonView.bind('ariaChecked').to(buttonView, 'isOn');
                buttonView.delegate('execute').to(menuView);
                buttonView.on('execute', () => {
                    const commandName = option.model === 'paragraph' ? 'paragraph' : 'heading';
                    editor.execute(commandName, { value: option.model });
                    editor.editing.view.focus();
                });
                if (option.model === 'paragraph') {
                    buttonView.bind('isOn').to(paragraphCommand, 'value');
                    commands.push(paragraphCommand);
                }
                else {
                    buttonView.bind('isOn').to(headingCommand, 'value', value => value === option.model);
                }
            }
            menuView.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled) => {
                return areEnabled.some(isEnabled => isEnabled);
            });
            return menuView;
        });
    }
}
