// 1.0.3
import { app } from "../../../../scripts/app.js";
import { api } from "../../../../scripts/api.js";
import { $el } from "../../../../scripts/ui.js";
import { $t } from "../common/i18n.js";

// 获取风格列表
let styles_list_cache = {}
let styles_image_cache = {}
async function getStylesList(name){
    if(styles_list_cache[name]) return styles_list_cache[name]
    else{
       const resp = await api.fetchApi(`/easyuse/prompt/styles?name=${name}`);
       if (resp.status === 200) {
            let data = await resp.json();
            styles_list_cache[name] = data;
            return data;
       }
       return undefined;
    }
}
async function getStylesImage(name, styles_name){
    if(!styles_image_cache[styles_name]) styles_image_cache[styles_name] = {}
    if(styles_image_cache[styles_name][name]) return styles_image_cache[styles_name][name]
    else{
       const resp = await api.fetchApi(`/easyuse/prompt/styles/image?name=${name}&styles_name=${styles_name}`);
       if (resp.status === 200) {
           const text = await resp.text()
           if(text.startsWith('http')){
               styles_image_cache[styles_name][name] = text
               return text
           }
           const url = `/easyuse/prompt/styles/image?name=${name}&styles_name=${styles_name}`
           styles_image_cache[styles_name][name] = url
           return url
       }
       return undefined;
    }
}

function getTagList(tags, styleName, language='en-US') {
    let rlist=[]
    tags.forEach((k,i) => {
        rlist.push($el(
            "label.easyuse-prompt-styles-tag",
            {
                dataset: {
                    tag: k['name'],
                    name: language == 'zh-CN' && k['name_cn'] ? k['name_cn'] : k['name'],
                    imgName: k['imgName'],
                    index: i
                },
                $: (el) => {
                    el.children[0].onclick = () => {
                        el.classList.toggle("easyuse-prompt-styles-tag-selected");
                    };
                    el.onmousemove = (e) => {
                        displayImage(el.dataset.imgName, styleName, e)
                    };
                    el.onmouseout = () => {
                        hiddenImage()
                    };
                    el.onmouseover = (e) => {
                        displayImage(el.dataset.imgName, styleName)
                    };
                },
            },
            [
                $el("input",{
                    type: 'checkbox',
                    name: k['name']
                }),
                $el("span",{
                    textContent: language == 'zh-CN' && k['name_cn'] ? k['name_cn'] : k['name'],
                })
            ]
        ))
    });
    return rlist
}

const foocus_base_path = "https://raw.githubusercontent.com/lllyasviel/Fooocus/main/sdxl_styles/samples/"
const empty_img = "data:image/jpeg;base64, "
async function displayImage(imgName, styleName) {
    var e = event || window.event;
    var img = document.getElementById("show_image_id");
    var pxy= img.parentElement.getBoundingClientRect();
    if(imgName) {
        const url = await getStylesImage(imgName, styleName)
        img.src = url
        img.onerror = _ =>{
            img.src = empty_img
        }
    }
    var scale = app?.canvas?.ds?.scale || 1;
    var x = (e.pageX-pxy.x-100)/scale;
    var y = (e.pageY-pxy.y+25)/scale;
    img.style.left = x+"px";
    img.style.top = y+"px";
    img.style.display = "block";
    img.style.borderRadius = "10px";
    img.style.borderColor = "var(--fg-color)"
    img.style.borderWidth = "1px";
    img.style.borderStyle = "solid";
}
function hiddenImage(){ //theEvent用来传入事件，Firefox的方式
    var img = document.getElementById('show_image_id');
    img.style.display = "none";
}

// StylePromptSelector
app.registerExtension({
    name: 'comfy.easyUse.styleSelector',
    async beforeRegisterNodeDef(nodeType, nodeData, app) {

        if(nodeData.name == 'easy stylesSelector'){
            // 创建时
            const onNodeCreated = nodeType.prototype.onNodeCreated;
            nodeType.prototype.onNodeCreated = function() {
                onNodeCreated ? onNodeCreated?.apply(this, arguments) : undefined;
                const styles_id =  this.widgets.findIndex((w) => w.name == 'styles');
                const language = localStorage['AGL.Locale'] || localStorage['Comfy.Settings.AGL.Locale'] || 'en-US'
                const list = $el("ul.easyuse-prompt-styles-list",[]);
                let styles_values = ''
                this.setProperty("values", [])

                let selector = this.addDOMWidget('select_styles',"btn",$el('div.easyuse-prompt-styles',[$el('div.tools', [
                        $el('button.delete',{
                            textContent: $t('Empty All'),
                            style:{},
                            onclick:()=>{
                                selector.element.children[0].querySelectorAll(".search").forEach(el=>{
                                    el.value = ''
                                })
                                selector.element.children[1].querySelectorAll(".easyuse-prompt-styles-tag-selected").forEach(el => {
                                    el.classList.remove("easyuse-prompt-styles-tag-selected");
                                    el.children[0].checked = false
                                })
                                selector.element.children[1].querySelectorAll(".easyuse-prompt-styles-tag").forEach(el => {
                                    el.classList.remove('hide')
                                })
                                this.setProperty("values", [])
                            }}
                        ),
                        $el('textarea.search',{
                            dir:"ltr",
                            style:{"overflow-y": "scroll"},
                            rows:1,
                            placeholder:$t("🔎 Type here to search styles ..."),
                            oninput:(e)=>{
                                let value = e.target.value
                                selector.element.children[1].querySelectorAll(".easyuse-prompt-styles-tag").forEach(el => {
                                    const name = el.dataset.name.toLowerCase()
                                    const tag = el.dataset.tag.toLowerCase()
                                    const lower_value = value.toLowerCase()
                                    if(name.indexOf(lower_value) != -1 || tag.indexOf(lower_value) != -1  || el.classList.value.indexOf("easyuse-prompt-styles-tag-selected")!=-1){
                                        el.classList.remove('hide')
                                    }
                                    else{
                                        el.classList.add('hide')
                                    }
                                })
                            }
                        })
                    ]),list,
                    $el('img',{id:'show_image_id',
                        style:{display:'none',position:'absolute'},
                        src:``,
                        onerror:()=>{
                            this.src = empty_img
                        }
                    })
                ]));

                Object.defineProperty(this.widgets[styles_id],'value',{
                    set:(value)=>{
                        styles_values = value
                        if(styles_values){
                            getStylesList(styles_values).then(_=>{
                                selector.element.children[1].innerHTML=''
                                if(styles_list_cache[styles_values]){
                                    let tags = styles_list_cache[styles_values]
                                    // 重新排序
                                    if(selector.value) tags = tags.sort((a,b)=> selector.value.includes(b.name) - selector.value.includes(a.name))
                                    this.properties["values"] = []
                                    let list = getTagList(tags, value, language);
                                    selector.element.children[1].append(...list)
                                    selector.element.children[1].querySelectorAll(".easyuse-prompt-styles-tag").forEach(el => {
                                        if (this.properties["values"].includes(el.dataset.tag)) {
                                            el.classList.add("easyuse-prompt-styles-tag-selected");
                                        }
                                        if(this.size?.[0]<150 || this.size?.[1]<150) this.setSize([425, 500]);
                                    })
                                }
                            })
                        }
                    },
                    get: () => {
                        return styles_values
                    }
                })

                
                let style_select_values = ''
                Object.defineProperty(selector, "value", {
                    set: (value) => {
                        setTimeout(_=>{
                            selector.element.children[1].querySelectorAll(".easyuse-prompt-styles-tag").forEach(el => {
                                let arr = value.split(',')
                                if (arr.includes(el.dataset.tag)) {
                                    el.classList.add("easyuse-prompt-styles-tag-selected");
                                    el.children[0].checked = true
                                }
                            })
                        },300)
                    },
                    get: () => {
                        selector.element.children[1].querySelectorAll(".easyuse-prompt-styles-tag").forEach(el => {
                            if(el.classList.value.indexOf("easyuse-prompt-styles-tag-selected")>=0){
                                if(!this.properties["values"].includes(el.dataset.tag)){
                                    this.properties["values"].push(el.dataset.tag);
                                }
                            }else{
                                if(this.properties["values"].includes(el.dataset.tag)){
                                    this.properties["values"]= this.properties["values"].filter(v=>v!=el.dataset.tag);
                                }
                            }
                        });
                        style_select_values = this.properties["values"].join(',');
                        return style_select_values;
                    }
                });

                let old_values = ''
                let style_lists_dom = selector.element.children[1]
                style_lists_dom.addEventListener('mouseenter', function (e) {
                    let value = ''
                    style_lists_dom.querySelectorAll(".easyuse-prompt-styles-tag-selected").forEach(el=> value+=el.dataset.tag)
                    old_values = value
                })
                style_lists_dom.addEventListener('mouseleave', function (e) {
                    let value = ''
                    style_lists_dom.querySelectorAll(".easyuse-prompt-styles-tag-selected").forEach(el=> value+=el.dataset.tag)
                    let new_values = value
                    if(old_values != new_values){
                        // console.log("选项发生了变化")
                        // 获取搜索值
                        const search_value = document.getElementsByClassName('search')[0]['value']
                        // 重新排序
                        const tags = styles_list_cache[styles_values].sort((a,b)=> new_values.includes(b.name) - new_values.includes(a.name))
                        style_lists_dom.innerHTML = ''
                        let list = getTagList(tags, styles_values, language);
                        style_lists_dom.append(...list)
                        style_lists_dom.querySelectorAll(".easyuse-prompt-styles-tag").forEach(el => {
                            if (new_values.includes(el.dataset.tag)) {
                                el.classList.add("easyuse-prompt-styles-tag-selected");
                                el.children[0].checked = true;
                            }
                            if(search_value){
                                if(el.dataset.name.indexOf(search_value) != -1 || el.dataset.tag.indexOf(search_value) != -1  || el.classList.value.indexOf("easyuse-prompt-styles-tag-selected")!=-1){
                                    el.classList.remove('hide')
                                }
                                else{
                                    el.classList.add('hide')
                                }
                            }

                        })
                    }
                })


                // 初始化
                setTimeout(_=>{
                    if(!styles_values) {
                        styles_values = 'fooocus_styles'
                        getStylesList(styles_values).then(_=>{
                            selector.element.children[1].innerHTML=''
                            if(styles_list_cache[styles_values]){
                                let tags = styles_list_cache[styles_values]
                                // 重新排序
                                if(selector.value) tags = tags.sort((a,b)=> selector.value.includes(b.name) - selector.value.includes(a.name))
                                let list = getTagList(tags, styles_values, language);
                                selector.element.children[1].append(...list)
                            }
                        })
                    }
                    if(this.size?.[0]<150 || this.size?.[1]<150) this.setSize([425, 500]);
                    //
                },100)

                return onNodeCreated;
            }
        }
    }
})