import flatpickr from "flatpickr";
import Choices from "choices.js";
import AACKEditor from "../../../vendor/ckeditor/build/ckeditor";
import jsonlint from 'jsonlint/lib/formatter';

class FormManager {
    _typeConfigs = {}
    _libs = {}

    isReady = false;

    _createTypeNode(type) {
        if (typeof this._typeConfigs[type] === 'undefined') {
            this._typeConfigs[type] = {
                defaultOptions: {},
                handler: undefined,
                initialized: false,
            }
        }
    }

    addTypeHandler(type, handler) {
        this._createTypeNode(type);
        this._typeConfigs[type].handler = handler;
    }

    setTypeDefaultOptions(type, defaultOptions) {
        this._createTypeNode(type);
        this._typeConfigs[type].defaultOptions = defaultOptions;
    }

    setLib(slug, lib) {
        // restrict slug to normalize, lib key, only allow a-z
        if (!slug.match(/[a-z]+/)) {
            throw new Error('Lib key is not following regex: [a-z]+');
        }
        this._libs[slug] = lib;
    }

    getLib(slug) {
        return this._libs[slug];
    }

    initialize(scopeEl = null) {
        if (scopeEl === null) {
            scopeEl = document.querySelector('body');
        }

        if (typeof scopeEl.nodeName === 'undefined') {
            console.warn('Could not initialize form, given element is not a html node.')
            return;
        }

        const libWrap = {
            _libs: this._libs,
            getLib: this.getLib
        };
        Object.keys(this._typeConfigs).forEach((type) => {
            let {
                defaultOptions,
                handler,
                initialized
            } = this._typeConfigs[type];

            let elements = this.findMatchingElements(type, scopeEl);
            elements.forEach((el) => {
                if (
                    typeof el.aaFormComponent === 'undefined'
                    || (typeof el.aaFormComponent !== 'undefined' && typeof el.aaFormComponent[type] === 'undefined')
                ) {
                    let formComponent = null;
                    if (typeof handler !== 'undefined') {
                        formComponent = handler(el, defaultOptions, libWrap);
                    }
                    if (formComponent) {
                        if (typeof el.aaFormComponent === 'undefined') {
                            el.aaFormComponent = {};
                        }
                        el.aaFormComponent[type] = formComponent;
                    }
                }
            });

            this._typeConfigs[type].initialized = true;
        });

        this.isReady = true;
    }

    findMatchingElements(type, scopeElement) {
        let typeClass = '.' + type;
        let selector = ':scope ' + typeClass;
        return [...scopeElement.querySelectorAll(selector)];
    }
}

let form = new FormManager();
window.AAForm = form;

// lib slug must follow format: [a-z]+
AAForm.setLib('ckeditor', AACKEditor)
AAForm.setLib('choicesjs', Choices)
AAForm.setLib('flatpickr', flatpickr)
AAForm.setLib('jsonLintFormat', jsonlint.formatter.formatJson)

// timings
const eventTimes = {
    initializing: 150,// leave a little time to register handlers
}

// global form init
const initForm = function () {
    // this event permit to alter handler config before global init
    let formInitEvent = new CustomEvent('aa_form_pre_init', {form: AAForm});
    document.body.dispatchEvent(formInitEvent);
    AAForm.initialize();
}
if (document.readyState === "complete" || document.readyState === "interactive") {
    // if document is loaded
    setTimeout(initForm, eventTimes.initializing);
} else {
    // if document is not yet loaded
    document.addEventListener("DOMContentLoaded", () => {
        setTimeout(initForm, eventTimes.initializing);
    });
}
