import Input from "../Input";
import InputFactory, {InputImplConfig} from "../InputFactory";

export default class TextEditor extends Input<string>{
    public buttons: Buttons = {};

    constructor(params: Partial<TextEditor>) {
        super(params);
        Object.assign(this, params);
    }

    public placeHtml(container: HTMLElement): void {
        const questionContainer = this.getQuestionContainer();
        questionContainer.classList.add("pad-text-editor-input");
        container.append(questionContainer);
        this.placedHtml.push(questionContainer);
    }

    protected getInputElement(): HTMLElement {
        const inputWrapper = document.createElement("div");
        inputWrapper.classList.add("pad-input-field");
        const textAreaElement = document.createElement("textarea");
        textAreaElement.id = this.questionId;
        textAreaElement.name = this.getFullPathName();
        inputWrapper.append(textAreaElement);

        textAreaElement.innerHTML = this.getDataNode().valueOrDefault ?? "";

        const windowWithType = window as Window & typeof globalThis & {planadayTinymceV8: any, tinymce: any};
        if ( typeof windowWithType.planadayTinymceV8 === "undefined") {
            import("../../../../../../../../../assets/js/tinymce/v8/tinymce.js").then(() => {
                windowWithType.planadayTinymceV8 = windowWithType.tinymce;
            });
        }

        this.initializeTinymce(textAreaElement);

        return inputWrapper;
    }

    protected getSubMenuItems(editor: any, subItemObject: Buttons){
        const subItems = [];

        for (const subItemsKey in subItemObject) {
            const item = subItemObject[subItemsKey];
            if (typeof item === "string") {
                subItems.push({
                    type: "menuitem",
                    text: subItemsKey,
                    onAction: () => {
                        editor.insertContent(item);
                    }
                })
            } else {
                subItems.push({
                    type: "nestedmenuitem",
                    text: subItemsKey,
                    getSubmenuItems: () => this.getSubMenuItems(editor, item)
                });
            }
        }

        return subItems;
    }

    protected initializeTinymce(target: HTMLTextAreaElement): void{
        const checkedWindow = window as Window & typeof globalThis & {planadayTinymceV8: any};
        setTimeout(() => {
            if (typeof checkedWindow.planadayTinymceV8 === 'undefined') {
                this.initializeTinymce(target);
                return;
            }

            checkedWindow.planadayTinymceV8.init(
                {
                    target: target,
                    plugins: "link",
                    menubar: "visualaid",
                    toolbar: "blocks | fontsize forecolor | bold italic underline | align | link" +
                        (!(Object.keys(this.buttons).length === 0 || Array.isArray(this.buttons)) ? " | planaday" : ""),
                    setup:
                        (editor: any) => {
                            if (!(Object.keys(this.buttons).length === 0 || Array.isArray(this.buttons))) editor.ui.registry.addMenuButton('planaday', {
                                text: 'Planaday',
                                fetch: (callback: any) => callback(this.getSubMenuItems(editor, this.buttons) as any[])
                            });

                            editor.on('input', () => {
                                this.value = editor.getContent();
                            });

                            this.onChange.add(event => {
                                if (editor.getContent() !== event.value) editor.setContent(event.value ?? "");
                            });

                            editor.on("change", () => {
                                this.saveValue();
                            })

                            this.getDataNode().onChange.add(event => {
                                editor.setContent(event.value ?? "");
                            });

                            this.getDataNode().onReset.add(() => {
                                this.value = undefined;
                                editor.setContent(this.getDataNode().valueOrDefault ?? "");
                            });
                        },
                    license_key: "gpl",
                    base_url: '/wp-content/plugins/planaday-connector/assets/js/tinymce/v8/',
                    branding: false,
                    promotion: false
                }
            );
        }, 10)
    }

}

export function addTextEditorToFactory(factory: InputFactory): void {
    factory.registerConstructor("textEditor", (config, params) => {
        const impl = config.impl;
        if (!isTextEditorConfig(impl)) return null;

        const textEditorParam: Partial<TextEditor> = params as Partial<TextEditor>;
        textEditorParam.buttons = impl.buttons;

        return new TextEditor(textEditorParam);
    });
}

function isTextEditorConfig(config: InputImplConfig): config is TextEditorConfig{
    return config.type === "textEditor";
}

interface TextEditorConfig extends InputImplConfig{
    type: "textEditor";
    buttons: Buttons;
}

interface Buttons {
    [name: string]: string|Buttons;
}