import { VDomModel, VDomRenderer } from '@jupyterlab/apputils';
import { interactiveItem, showPopup, TextItem } from '@jupyterlab/statusbar';
import { nullTranslator } from '@jupyterlab/translation';
import { Menu } from '@lumino/widgets';
import React from 'react';
import { Mode } from '.';
/**
 * A pure function that returns a tsx component for an editor syntax item.
 *
 * @param props: the props for the component.
 *
 * @returns an editor syntax component.
 */
function EditorSyntaxComponent(props) {
    return React.createElement(TextItem, { source: props.mode, onClick: props.handleClick });
}
/**
 * StatusBar item to change the language syntax highlighting of the file editor.
 */
export class EditorSyntaxStatus extends VDomRenderer {
    /**
     * Construct a new VDomRenderer for the status item.
     */
    constructor(opts) {
        super(new EditorSyntaxStatus.Model());
        /**
         * Create a menu for selecting the mode of the editor.
         */
        this._handleClick = () => {
            const modeMenu = new Menu({ commands: this._commands });
            const command = 'codemirror:change-mode';
            if (this._popup) {
                this._popup.dispose();
            }
            Mode.getModeInfo()
                .sort((a, b) => {
                const aName = a.name || '';
                const bName = b.name || '';
                return aName.localeCompare(bName);
            })
                .forEach(spec => {
                if (spec.mode.indexOf('brainf') === 0) {
                    return;
                }
                const args = {
                    insertSpaces: true,
                    name: spec.name
                };
                modeMenu.addItem({
                    command,
                    args
                });
            });
            this._popup = showPopup({
                body: modeMenu,
                anchor: this,
                align: 'left'
            });
        };
        this._popup = null;
        this._commands = opts.commands;
        this.translator = opts.translator || nullTranslator;
        const trans = this.translator.load('jupyterlab');
        this.addClass(interactiveItem);
        this.title.caption = trans.__('Change text editor syntax highlighting');
    }
    /**
     * Render the status item.
     */
    render() {
        if (!this.model) {
            return null;
        }
        return (React.createElement(EditorSyntaxComponent, { mode: this.model.mode, handleClick: this._handleClick }));
    }
}
/**
 * A namespace for EditorSyntax statics.
 */
(function (EditorSyntaxStatus) {
    /**
     * A VDomModel for the current editor/mode combination.
     */
    class Model extends VDomModel {
        constructor() {
            super(...arguments);
            /**
             * If the editor mode changes, update the model.
             */
            this._onMIMETypeChange = (mode, change) => {
                const oldMode = this._mode;
                const spec = Mode.findByMIME(change.newValue);
                this._mode = spec.name || spec.mode;
                this._triggerChange(oldMode, this._mode);
            };
            this._mode = '';
            this._editor = null;
        }
        /**
         * The current mode for the editor. If no editor is present,
         * returns the empty string.
         */
        get mode() {
            return this._mode;
        }
        /**
         * The current editor for the application editor tracker.
         */
        get editor() {
            return this._editor;
        }
        set editor(editor) {
            const oldEditor = this._editor;
            if (oldEditor !== null) {
                oldEditor.model.mimeTypeChanged.disconnect(this._onMIMETypeChange);
            }
            const oldMode = this._mode;
            this._editor = editor;
            if (this._editor === null) {
                this._mode = '';
            }
            else {
                const spec = Mode.findByMIME(this._editor.model.mimeType);
                this._mode = spec.name || spec.mode;
                this._editor.model.mimeTypeChanged.connect(this._onMIMETypeChange);
            }
            this._triggerChange(oldMode, this._mode);
        }
        /**
         * Trigger a rerender of the model.
         */
        _triggerChange(oldState, newState) {
            if (oldState !== newState) {
                this.stateChanged.emit(void 0);
            }
        }
    }
    EditorSyntaxStatus.Model = Model;
})(EditorSyntaxStatus || (EditorSyntaxStatus = {}));
//# sourceMappingURL=syntaxstatus.js.map