"use strict";

import {Utils} from "../Utils/Utils.ecma.js";

/**
 * @class MainFormView
 * @constructor
 * @param {!OpoTests} ot
 * @returns {void}
 * @access public
 * @static
 */
export const MainFormView = (function(){

    /**
     * @constructs MainFormView
     * @param {!OpoTests} ot
     * @returns {void}
     * @access private
     * @static
     */
    const MainFormView = function(ot){

        /** @type {MainFormView} */
        const self = this;

        /**
         * @returns {void}
         * @access private
         */
        const constructor = () => {};

        /**
         * @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null] 
         * @returns {Array.<any>}
         * @access public
         */
        this.create = (inputs = null) => {
            
            /** @type {Object.<string, [number, number, Array.<number>]>} */
            const groups = {}, 
                  /** @type {Array.<[string, {data_visible: boolean, data_selected: boolean, data_i: number}, Array.<any>]>} */
                  subjects = [];
            /** @type {number} */
            let k = 0;

            ot.database.forEach((block, i) => {

                if(block.group){
                    if(groups[block.group]){
                        groups[block.group][1] += block.queries.length;
                        groups[block.group][2].push(i);
                        return;
                    };
                    groups[block.group] = [k, block.queries.length, [i]];
                };
                k ++;

                subjects.push(["li", {
                    data_visible : true, 
                    data_selected : false, 
                    data_is : i
                }, [
                    ot.comp.checkbox("blocks[]", false, (item, event) => {
                        item.closest("li").setAttribute("data-selected", item.checked);
                    }, (
                        `<span class="questions-number" title="` + ot.i18n.get("questions_number") + `">` + block.queries.length + `</span>` + 
                        `<span class="group" title="` + block.origin + `">` + block.origin + `</span>` + 
                        `<span class="title" title="` + block.title + `">` + block.title + `</span>`
                    ))
                ]]);
            });

            Object.values(groups).forEach(([k, length, i]) => {
                subjects[k][1].data_is = i.join(",");
                subjects[k][2][0][2][2][2] = subjects[k][2][0][2][2][2].replace(/(class="questions-number"[^>]*>)[0-9]+</, `$1` + length + `<`);
            });

            console.log(subjects);
            
            return ot.comp.form("test_creator", [
                ["custom", "blocks", ["div", {data_show_selected : false}, [
                    ot.comp.group("search", 
                        ["label", {
                            for : "search", 
                            data_i18n : "search", 
                            data_i18n_without : true, 
                            title : ot.i18n.get("search")
                        }, [
                            ot.comp.icon("search"),
                            ot.comp.i18n("search")
                        ]], 
                        ot.comp.text("search", null, 250, null, (item, event) => {

                            /** @type {Array.<[boolean|null, boolean, string]>} */
                            const value = [];

                            item.value.trim().toLowerCase().replace(/(^|[&\|])(\!)?([^&\|]+)/g, (_, operator, not, data) => {
                                (data = data.trim()) && 
                                value.push([operator == "&" ? true : operator == "|" ? false : null, not, data]);
                            });

                            document.querySelectorAll("[data-i][data-i18n=blocks] li label>[data-i18n]").forEach(span => {

                                /** @type {HTMLLiElement} */
                                const list_item = span.closest("li");

                                if(!value.length)
                                    list_item.setAttribute("data-visible", true);
                                else{

                                    /** @type {string} */
                                    const text = list_item.textContent.trim().toLowerCase();
                                    /** @type {ok} */
                                    let ok = true;

                                    value.every(([operator, not, data]) => {

                                        /** @type {boolean} */
                                        let subok = not ? !text.includes(data) : text.includes(data);

                                        if(operator)
                                            return ok = ok && subok;
                                        if(operator === false)
                                            return ok || (ok = subok);

                                        ok = subok;

                                        return true;
                                    });
                                    list_item.setAttribute("data-visible", ok);

                                };
                            });

                        }, "search"), 
                        ot.comp.button("select_all_visible", (item, event) => {
                            document.querySelectorAll("[data-i][data-i18n=blocks] li[data-visible=true]").forEach(list_item => {
                                list_item.querySelector("[type=checkbox]").checked = true;
                            });
                        }), 
                        ot.comp.button("unselect_all_visible", (item, event) => {
                            document.querySelectorAll("[data-i][data-i18n=blocks] li[data-visible=true]").forEach(list_item => {
                                list_item.querySelector("[type=checkbox]").checked = false;
                            });
                        }), 
                        ot.comp.checkbox("show_selected", false, (item, event) => {
                            item.closest("div").parentNode.setAttribute("data-show-selected", item.checked);
                        }, null, true)
                    ), ["nav", null, [
                        ["ul", null, subjects]
                    ]]
                ]]], 
                ["number", "minimum_questions", ot.settings.get("minimum_questions", inputs, 20), 1, 250], 
                ["number", "maximum_questions", ot.settings.get("maximum_questions", inputs, 200), 1, 250], 
                ["number", "minimum_answers", ot.settings.get("minimum_answers", inputs, 4), 1, 20], 
                ["number", "maximum_answers", ot.settings.get("maximum_answers", inputs, 4), 1, 20], 
                ["checkbox", "allow_unique_right", ot.settings.get("allow_unique_right", inputs, true)],
                ["checkbox", "allow_multiple_answers", ot.settings.get("allow_multiple_answers", inputs, false)],
                ["checkbox", "allow_all_answers_false", ot.settings.get("allow_all_answers_false", inputs, true)],
                ["checkbox", "allow_all_answers_true", ot.settings.get("allow_all_answers_true", inputs, false)],
                ["checkbox", "allow_repeated_questions", ot.settings.get("allow_repeated_questions", inputs, true)],
                ["checkbox", "show_rights", ot.settings.get("show_rights", inputs, false)],
                ["checkbox", "show_results", ot.settings.get("show_results", inputs, true)],
                ["checkbox", "lock_mode", ot.settings.get("lock_mode", inputs, false)],
                ["number", "marks_over", ot.settings.get("marks_over", inputs, 10), 1, 100, .01], 
                ["number", "marks_rest", ot.settings.get("marks_rest", inputs, .3), .01, 20, .01], 
                ["number", "marks_decimals", ot.settings.get("marks_decimals", inputs, 2), 0, 10], 
            ], (item, event) => {
                event.preventDefault();

                /** @type {Object.<string, string|number|boolean|Array.<string|number|boolean>>} */
                const data = ot.comp.get_form_data(item);

                if(data.blocks.some(has => has)){

                    /** @type {NodeListOf<HTMLLIElement>} */
                    const blocks_items = document.querySelectorAll("[data-i][data-i18n=blocks] li"), 
                          /** @type {Array.<number>} */
                          blocks = [];

                    data.blocks.forEach((selected, i) => {
                        selected && blocks.push(...blocks_items[i].getAttribute("data-is").split(",").map(Number));
                    })

                    data.blocks = blocks;

                    // console.log(ot.database[6].queries[0]);
                    // console.log(ot.format.check(
                    //     "Se modifica el artículo 49 de la Carta Magna de 1978 para sustituir el término 'disminuidos' por 'personas con discapacidad'.", 
                    //     ["Se modifica el artículo 49 de la {ce78} para sustituir el término 'disminuidos' por 'personas con discapacidad'."], 
                    // {}, []));

                    // console.log(ot.format.check("Transistores.", [
                    //     "{AI}.", 
                    //     "Computación cuántica.", 
                    //     "{NLP}.", 
                    //     "Redes Neuronales.", 
                    //     "Computación en la nube.", 
                    //     "Big Data.", 
                    //     "Computación Ubicua.", 
                    //     "Nacimiento del Lenguaje Java."
                    // ], {}, []))

                    ot.tests.build(data);

                }else 
                    ot.alert("need_one_block_at_least");

                return false;
            });
        };

        /**
         * @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null] 
         * @returns {void}
         * @access public
         */
        this.build = (inputs = null) => {

            /** @type {HTMLMainElement} */
            const main = document.querySelector("main");

            main.innerHTML = ``;
            Utils.html(main, self.create(inputs));

        };

        constructor();

    };

    return MainFormView;
})();