export function activateOptionsMenu(
    disableSidenotes: () => void,
    enableSidenotes: () => void,
    disableViewers: () => void,
    enableViewers: () => void,
): void {
    const main = document.querySelector("main");
    if (!main) {
        return;
    }

    const popover = document.createElement("div");
    popover.id = "options-menu";
    popover.popover = "auto";
    const menu = document.createElement("menu");

    const newInput = (name: string, labelText: string, ty = "checkbox") => {
        const li = document.createElement("li");
        const inp = document.createElement("input");
        inp.type = ty;
        inp.id = name;
        inp.name = name;

        const label = document.createElement("label");
        label.htmlFor = name;
        label.innerText = labelText;
        if (ty === "range") {
            li.appendChild(label);
            li.appendChild(document.createElement("br"));
        }
        li.appendChild(inp);
        if (ty !== "range") {
            li.appendChild(label);
        }

        menu.appendChild(li);

        return inp;
    };
    const activateCheckbox = (
        inp: HTMLInputElement,
        inpUpdate: () => void,
        defaultChecked = false,
    ) => {
        const localStorageKey = `options.${inp.id}`;
        const item = localStorage.getItem(localStorageKey);
        inp.checked = defaultChecked ? item !== "false" : item === "true";
        const inpUpdateAndSave = () => {
            inpUpdate();
            localStorage.setItem(localStorageKey, `${!!inp.checked}`);
        };
        inpUpdateAndSave();
        inp.addEventListener("change", inpUpdateAndSave);
    };
    const styleVarCheckbox = (
        inp: HTMLInputElement,
        styleVar: string,
        checkedVal: string,
        uncheckedVal: string,
    ) =>
        activateCheckbox(inp, () =>
            document.documentElement.style.setProperty(
                styleVar,
                inp.checked ? checkedVal : uncheckedVal,
            ),
        );
    const scriptingCheckbox = (
        inp: HTMLInputElement,
        disable: () => void,
        enable: () => void,
    ) =>
        activateCheckbox(
            inp,
            () => (inp.checked ? enable() : disable()),
            true,
        );
    const styleVarRange = (
        inp: HTMLInputElement,
        styleVar: string,
        unit: string,
        list: number[],
    ) => {
        const [min, max] = [list.at(0)!, list.at(-1)!];
        inp.min = "" + min;
        inp.max = "" + max;

        const datalist = document.createElement("datalist");
        datalist.id = inp.id + "-datalist";
        for (const n of list) {
            const opt = document.createElement("option");
            opt.value = "" + n;
            datalist.appendChild(opt);
        }
        inp.parentNode?.appendChild(datalist);
        inp.setAttribute("list", datalist.id);

        const localStorageKey = `options.${inp.id}`;
        const item = parseFloat(localStorage.getItem(localStorageKey) ?? "");
        inp.value =
            "" +
            (Number.isFinite(item) && item >= min && item <= max
                ? item
                : (min + max) / 2);
        const inpUpdateAndSave = () => {
            document.documentElement.style.setProperty(
                styleVar,
                inp.value + unit,
            );
            localStorage.setItem(localStorageKey, inp.value);
        };
        inpUpdateAndSave();
        inp.addEventListener("change", inpUpdateAndSave);
    };

    const justifyInp = newInput("justify", "Justify");
    styleVarCheckbox(justifyInp, "--alignment", "justify", "start");
    const hyphenationInp = newInput("hyphenation", "Auto\u2010hyphenate");
    styleVarCheckbox(hyphenationInp, "--hyphenation", "auto", "manual");
    const widthInp = newInput("page-width", "Width", "range");
    const widthList = Array.from(
        Array(7)
            .keys()
            .map(n => 4 * n + 30),
    );
    styleVarRange(widthInp, "--main-width", "em", widthList);
    const sidenotesInp = newInput("sidenotes", "Sidenotes");
    scriptingCheckbox(sidenotesInp, disableSidenotes, enableSidenotes);
    const viewersInp = newInput("viewers", "Image embiggener");
    scriptingCheckbox(viewersInp, disableViewers, enableViewers);

    popover.appendChild(menu);

    const optionsButton = document.createElement("button");
    optionsButton.id = "options-button";
    optionsButton.popoverTargetElement = popover;
    optionsButton.textContent = "\u2699\ufe0e";

    main.appendChild(popover);
    main.appendChild(optionsButton);
}
