//injectConfig library by @theripper93
//License: MIT
//Documentation: https://github.com/theripper93/injectConfig

export const injectConfig = {
    inject: function injectConfig(app,html,data,object){
        this._generateTabStruct(app,html,data,object);
        const tabSize = data.tab?.width ?? 100;
        object = object || app.object;
        const moduleId = data.moduleId;
        let injectPoint
        if(typeof data.inject === "string"){
            injectPoint = html.find(data.inject).first().closest(".form-group");
        }else{
            injectPoint = data.inject;
        }
        injectPoint = injectPoint ? $(injectPoint) : (data.tab ? html.find("form > .tab").last() : html.find(".form-group").last());
        let injectHtml = "";
        for(const [k,v] of Object.entries(data)){
            if(k === "moduleId" || k === "inject" || k === "tab") continue;
            const elemData = data[k];
            const flag = "flags." + moduleId + "." + (k || "");
            const flagValue = object?.getFlag(moduleId, k) ?? elemData.default ?? getDefaultFlag(k);
            const notes = v.notes ? `<p class="notes">${v.notes}</p>` : "";
            v.label = v.units ? v.label+`<span class="units"> (${v.units})</span>` : v.label;
            switch(elemData.type){
                case "text":
                    injectHtml += `<div class="form-group">
                        <label for="${k}">${v.label || ""}</label>
                            <input type="text" name="${flag}" value="${flagValue}" placeholder="${v.placeholder || ""}">${notes}
                    </div>`;
                    break;
                case "number":
                    injectHtml += `<div class="form-group">
                        <label for="${k}">${v.label || ""}</label>
                            <input type="number" name="${flag}" min="${v.min}" max="${v.max}" step="${v.step ?? 1}" value="${flagValue}" placeholder="${v.placeholder || ""}">${notes}
                    </div>`;
                    break;
                case "checkbox": 
                    injectHtml += `<div class="form-group">
                        <label for="${k}">${v.label || ""}</label>
                            <input type="checkbox" name="${flag}" ${flagValue ? "checked" : ""}>${notes}
                    </div>`;
                    break;
                case "select":
                    injectHtml += `<div class="form-group">
                        <label for="${k}">${v.label || ""}</label>
                            <select name="${flag}">`;
                    for(const [i,j] of Object.entries(v.options)){
                        if(j.optgroup){
                            injectHtml += j.optgroup.start ? `<optgroup label="${j.optgroup.label}">` : "</optgroup>" ;
                        }else{
                            injectHtml += `<option value="${i}" ${flagValue === i ? "selected" : ""}>${j}</option>`;
                        }
                    }
                    injectHtml += `</select>${notes}
                    </div>`;
                    break;
                case "range":
                    injectHtml += `<div class="form-group">
                        <label for="${k}">${v.label || ""}</label>
                        <div class="form-fields">
                            <input type="range" name="${flag}" value="${flagValue}" min="${v.min}" max="${v.max}" step="${v.step ?? 1}">
                            <span class="range-value">${flagValue}</span>
                        </div>
                        ${notes}
                    </div>`;
                    break;
                case "color":
                    injectHtml += `<div class="form-group">
                        <label for="${k}">${v.label || ""}</label>
                        <div class="form-fields">
                            <input class="color" type="text" name="${flag}" value="${flagValue}">
                            <input type="color" data-edit="${flag}" value="${flagValue}">
                        </div>
                        ${notes}
                    </div>`;
                    break;
                case "custom":
                    injectHtml += v.html;
                    break;
            }
            if(elemData.type?.includes("filepicker")){
                const fpType = elemData.type.split(".")[1] || "imagevideo";
                injectHtml += `<div class="form-group">
                <label for="${k}">${v.label || ""}</label>
                <div class="form-fields">     
                    <button type="button" class="file-picker" data-extras="${elemData.fpTypes ? elemData.fpTypes.join(",") : ""}" data-type="${fpType}" data-target="${flag}" title="Browse Files" tabindex="-1">
                        <i class="fas fa-file-import fa-fw"></i>
                    </button>
                    <input class="image" type="text" name="${flag}" placeholder="${v.placeholder || ""}" value="${flagValue}">
                </div>${notes}
            </div>`;
            }
        }
        injectHtml = $(injectHtml);
        injectHtml.on("click", ".file-picker", this.fpTypes,_bindFilePicker);
        injectHtml.on("change", `input[type="color"]`, _colorChange);
        html.on("click", ".tabs .item", (e)=>{
            app._activeTab = $(e.currentTarget).data("tab");
        });
        if(data.tab){
            const injectTab = createTab(data.tab.name, data.tab.label, data.tab.icon).append(injectHtml);
            injectPoint.after(injectTab);
            if(app._activeTab) html.find(`.item[data-tab="${app._activeTab}"]`)[0]?.click();
            app?.setPosition({"height" : "auto", "width" : data.tab ? app.options.width + tabSize : "auto"});
            return injectHtml;
        }
        injectPoint.after(injectHtml);
        if(app)app?.setPosition({"height" : "auto", "width" : data.tab ? app.options.width + tabSize : "auto"});
        return injectHtml;

        function createTab(name,label,icon){
            
            /*let tabs = html.find(".sheet-tabs").last();
            if(!tabs.length) tabs = html.find(`nav[data-group="main"]`);*/
            const tabs = html.find(".sheet-tabs").first().find(".item").last();
            const tab = `<a class="item" data-tab="${name}"><i class="${icon}"></i> ${label}</a>`;
            tabs.after(tab);
            const tabContainer = `<div class="tab" data-tab="${name}"></div>`
            return $(tabContainer);
        }
    
    
        function getDefaultFlag(inputType){
            switch(inputType){
                case "number":
                    return 0;
                case "checkbox":
                    return false;
            }
            return "";
        }
    
        function _colorChange(e){
            const input = $(e.target);
            const edit = input.data("edit");
            const value = input.val();
            injectHtml.find(`input[name="${edit}"]`).val(value);
        }
    
        function _bindFilePicker(event) {
        event.preventDefault();
        const button = event.currentTarget;
        const input = $(button).closest(".form-fields").find("input") || null;
        const extraExt = button.dataset.extras ? button.dataset.extras.split(",") : [];
        const options = {
            field: input[0],
            type: button.dataset.type,
            current: input.val() || null,
            button: button,
        }
        const fp = new FilePicker(options);
        fp.extensions ? fp.extensions.push(...extraExt) : fp.extensions = extraExt;
        return fp.browse();
        }
    
    },
    quickInject: function quickInject(injectData, data){
        injectData = Array.isArray(injectData) ? injectData : [injectData];
        for(const doc of injectData){
            let newData = data
            if(doc.inject){
                newData = JSON.parse(JSON.stringify(data))
                data.inject = doc.inject;
            }
            Hooks.on(`render${doc.documentName}Config`, (app,html)=>{ injectConfig.inject(app,html,newData) });
        }

    },
    _generateTabStruct : function _generateTabStruct(app,html,data,object){
        const isTabs = html.find(".sheet-tabs").length;
        const useTabs = data.tab
        if(isTabs || !useTabs) return;
        const tabSize = data.tab?.width || 100;
        const layer = app?.object?.layer?.options?.name
        const icon = $(".main-controls").find(`li[data-canvas-layer="${layer}"]`).find("i").attr("class")

        const $tabs = $(`<nav class="sheet-tabs tabs">
        <a class="item active" data-tab="basic"><i class="${icon}"></i> ${game.i18n.localize("LIGHT.HeaderBasic")}</a>
        </nav>
        <div class="tab active" data-tab="basic"></div>`);
        //move all content of form into tab
        const form = html.find("form").first();
        form.children().each((i,e)=>{
            $($tabs[2]).append(e);
        });
        
        form.append($tabs);
        const submitButton = html.find("button[type='submit']").first();
        form.append(submitButton);

        html.on("click", ".item", (e)=>{
            html.find(".item").removeClass("active");
            $(e.currentTarget).addClass("active");
            html.find(".tab").removeClass("active");
            html.find(`[data-tab="${e.currentTarget.dataset.tab}"]`).addClass("active");
            app.setPosition({"height" : "auto", "width" : data.tab ? app.options.width + tabSize : "auto"});
        });
    }
}
