import flatpickr from "flatpickr";
import Choices from "choices.js";
import AACKEditor from "../../../vendor/ckeditor/build/ckeditor";

class FormManager {
    _debug = false;
    _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;
        if (this._debug) {
            console.log('added handler:');
            console.log(this._typeConfigs[type]);
        }
    }

    setTypeDefaultOptions(type, defaultOptions) {
        this._createTypeNode(type);
        this._typeConfigs[type].defaultOptions = defaultOptions;
        if (this._debug) {
            console.log('added handler config:');
            console.log(this._typeConfigs[type]);
        }
    }

    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) {
        if (typeof this._libs[slug] === 'undefined') {
            console.log('lib "' + slug + '" does not exist in form manager');
        }
        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.')
            console.log(element);
            return;
        }

        console.log('Initializing form handlers:');
        console.log(this);

        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);
                    } else {
                        console.log('No handler for type:' + type);
                    }
                    if (formComponent) {
                        if (typeof el.aaFormComponent === 'undefined') {
                            el.aaFormComponent = {};
                        }
                        el.aaFormComponent[type] = formComponent;
                    }

                    if (this._debug) {
                        console.log(el);
                        console.log(formComponent);
                    }
                } else {
                    console.log('form el already initialized on:');
                    console.log(el);
                }
            });

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

        this.isReady = true;
    }

    findMatchingElements(type, scopeElement) {
        let typeClass = '.' + type;
        if (this._debug) {
            console.log('searching form el with class:', typeClass);
        }
        let selector = ':scope ' + typeClass;
        let elements = [...scopeElement.querySelectorAll(selector)];
        if (this._debug) {
            console.log(elements.length + ' found with "' + selector + '"', '(for type: "' + type + '")');
        }
        return elements;
    }
}

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)

// 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);
    });
}
