import { e } from "./helper.ts"
import { bangs } from "./query.ts"
import { status } from "./ui.ts"
import { pw_modal } from "./pwmodal.ts"
import fuzzysort from "./fuzzysort.js"

export function section_info_start() {
    return e("section", { class: "info" },
        e("h1", {}, "Fastbangs"),
        e("p", {}, `
            This application provides a way to (mostly) locally handle search bangs. To use it:
        `),
        e("ul", {},
            e("li", {}, "Select a fallback search engine, used when a search doesn't contain a bang"),
            e("li", {}, "Add this search engine to your browser, or bookmark this page"),
        ),
        e("span", {}, "Can't find a search engine? "), e("a", { href: "#~submit" }, "Propose or change a bang."),
    )
}

export function section_engine_select() {
    const select = async (e: string) => {
        const engine = e.toLowerCase()
        if (!(await bangs)[engine]) return status("error", `Engine ${JSON.stringify(e)} does not exist.`)
        window.location.hash = `#${e}`
    }

    const listing = e("ul", {})
    bangs.then(bangs => {
        for (const key in bangs) if (bangs[key]!.pinned) {
            listing.append(e("li", { class: "pinned", onclick: () => select(key) }, bangs[key]!.name ?? key))
        }
    })


    const submit = e("button", {}, "Select")
    submit.addEventListener("click", () => select(input.value))

    const searchResults = e("ul", { class: "dropdown" })

    const input = e("input", { type: "search" })
    input.addEventListener("keydown", ev => {
        if (ev.code == "Enter") select(input.value)
    })
    input.addEventListener("keyup", _ => {
        setSearchResults(searchResults, input, () => submit.click())
    })

    const manualInput = e("div", { id: "engine-select-manual" },
        e("label", {}, "Search engines:"),
        input,
        submit,
        searchResults
    )

    return e("section", { class: "engine-select" },
        e("h2", {}, "Select a search engine"),
        manualInput,
        listing
    )
}

export function section_admin_btn() {
    const modal = pw_modal()

    const btn = e("button", {
        class: "open-modal",
        onclick: () => modal.showModal()
    }, "Admin Login")

    return e("section", {class: "admin-btn"},
        btn,
        modal)
}

interface FuzzItem<E> { score: number, obj: E }
let bangsSearch: Promise<(query: string) => FuzzItem<{bang: string, name: string, url: string}>[]>
        | undefined = undefined;

function setSearchResults(ul: HTMLElement, input: HTMLInputElement, submit: () => void) {
    if (bangsSearch === undefined) {
        bangsSearch = bangs.then(bangs => {
            const searchSpace: {bang: string, name: string, url: string}[] = []
            for (const k in bangs) {
                searchSpace.push({
                    bang: k,
                    name: bangs[k]!.name!,
                    url: bangs[k]!.url!
                })
            }
            return q => fuzzysort.go(q, searchSpace, {
                threshhold: -5000,
                limit: 5,
                keys: ["bang", "name"],
            })
        })
    }

    bangsSearch!.then(fs => {
        ul.innerHTML = ""
        const results = fs(input.value)

        if (results.length === 0)
            ul.style.display = "none"
        else {
            ul.style.display = "flex"
            for (const r of results) {
                const it = r.obj
                const li = e("li", {},
                    e("p", { class: "name" }, it.name),
                    e("p", { class: "bang" }, it.bang))
                li.addEventListener("click", () => {
                    input.value = it.bang
                    submit()
                })
                ul.appendChild(li)
            }
        }
    })
}
