
const K = (function() {
    function get(selector_or_node) {
        let result = selector_or_node;
        if (typeof selector_or_node === "string") {
            result = document.querySelector(selector_or_node);
        }
        //console.log("NODE: " + selector_or_node + " "
        //    + typeof result + " " + result.nodeName);
        return result;
    }

    function getv(selector) {
        return document.querySelectorAll(selector);
    }

    function visible(node, new_state) {
        const nd = K.get(node);
        if (!nd) { console.warn("K.visible: element not found:", node); return false; }
        let result = nd;
        if (new_state === "hide") {
            nd.setAttribute("original-display", nd.style.display);
            nd.style.display = "none";
        } else if (new_state === "show") {
            nd.style.display = nd.getAttribute("original-display");
        } else if (new_state) {
            alert("Klammertext: Bad visible state for function K.visible: "
                  + new_state);
        } else {
            result = nd.style.display !== "none";
        }
        return result;
    }

    async function fetch_html(url) {
	//console.log("fetch_html: " + url);
        return await (await fetch(url)).text();
    }

    async function load(node, url) {
        const nd = get(node);
        nd.innerHTML = await fetch_html(url);
    }

    function width(node, new_width) {
        let nd = K.get(node);
        if (nd === null || typeof nd === 'undefined') {
            console.warn("K.width: element not found:", node);
            return 0;
        }
        let result;
        if (new_width !== undefined) {
            if (!nd.style) {
                nd.style = {};
            }
            new_width = Math.max(0, new_width);
            nd.style.width = new_width + "px";
            result = new_width;
        } else {
            result = nd.offsetWidth;
        }
        return result;
    }

    function height(node, new_height) {
        let nd = K.get(node);
        if (nd === null) {
            console.warn("K.height: element not found:", node);
            return 0;
        }
        //console.log("height: " + node + " " + nd);
        let result = nd;
        if (new_height !== undefined) {
            new_height = Math.max(0, new_height);
            nd.style.height = new_height + "px";
            result = new_height;
        } else {
            result = nd.offsetHeight;
        }
        return result;
    }

    function top(node) {
        return K.get(node).getBoundingClientRect().top;
    }

    function bottom(node) {
        return K.get(node).getBoundingClientRect().bottom;
    }

    function left(node) {
        return K.get(node).getBoundingClientRect().left;
    }

    function right(node) {
        return K.get(node).getBoundingClientRect().right;
    }

    function attr(node, attr_name, new_value) {
        const nd = K.get(node);
        if (!nd) { console.warn("K.attr: element not found:", node); return undefined; }
        let result = new_value;
        if (new_value) {
            nd.setAttribute(attr_name, new_value);
        } else {
            result = nd.getAttribute(attr_name);
        }
        return result;
    }

    function map(selector, func) {
        return [...(K.getv(selector))].map(func);
    }

    function has_class(node_or_vector, cls) {
        if (!node_or_vector) { console.warn("K.has_class: null element"); return node_or_vector; }
        let result;
        if (node_or_vector.length) {
            [...node_or_vector].map(function(elt) {
                result = elt.classList.contains(cls);
            });
        } else {
            result = node_or_vector.classList.contains(cls);
        }
        return result;
    }

    function add_class(node_or_vector, cls) {
        if (!node_or_vector) { console.warn("K.add_class: null element"); return node_or_vector; }
        if (node_or_vector.length) {
            [...node_or_vector].map(function(elt) {
                elt.classList.add(cls);
            });
        } else {
            node_or_vector.classList.add(cls);
        }
        return node_or_vector;
    }

    function remove_class(node_or_vector, cls) {
        if (!node_or_vector) { console.warn("K.remove_class: null element"); return node_or_vector; }
        if (node_or_vector.length) {
            [...node_or_vector].map(function(elt) {
                elt.classList.remove(cls);
            });
        } else {
            node_or_vector.classList.remove(cls);
        }
        return node_or_vector;
    }

    function text(node, new_text) {
        let result = new_text;
        if (new_text) {
            K.get(node).textContent = new_text;
        } else {
            result = K.get(node).textContent;
        }
        return result;
    }

    function style(node, name, new_value) {
        const nd = K.get(node);
        let result;
        if (new_value) {
            nd.style.setProperty(name, new_value);
            result = new_value;
        } else {
             result = window.getComputedStyle(nd).getPropertyValue(name);
        }
        return result;
    }

    function hpad(selector) {
        const node = K.get(selector);
        let result = parseInt(K.style(node, "padding-left"))
            + parseInt(K.style(node, "padding-right"));
        return result;
    }
    return {add_class, attr, bottom, get, getv, has_class,
            height, hpad, left, load, map, remove_class, right,
            style, text, top, visible, width};

}());



function current_basename()
{
    //var result = window.location.hash.toString().split("#")[1];
    let parts = window.location.href.split("#");
    let result;
    if (parts.length > 1) {
        result = parts[1];
    } else {
        result = "";
    }
    return result;
}


function search_not_active() {
    return document.activeElement.getAttribute("id") !== "search_input";
}

function define_keypress(letter, id) {
    let uppercase = letter.charCodeAt();
    let lowercase = uppercase + 32;
    K.get("html").addEventListener(
        "keypress",
        function (event) {
            if (search_not_active()) {
                if (event.which === uppercase || event.which === lowercase) {
                    K.get(id).click();
                }
            }
        });
}

function update_page_title(element) {
    let element_text = element.firstChild;
    let regex = /((?:Part )?[0-9.]*)(.*)/;
    let parts = regex.exec(element_text);
    let title;
    if (element_text) {
        if (!parts[1]) {
            title = parts[2].trim();
        } else {
            title = parts[1] + " - " + parts[2];
        }
        K.text("title", title);
   }
}

//window.scrollY + document.querySelector('#elementId')
//    .getBoundingClientRect().top // Y

function count_highlighted_toc_items() {
    const highlighted = K.map(
        ".section-title",
        function (o) {
            return K.has_class(o, "highlight");
        });
    const count = highlighted.filter(
        function (x) {
            return x === true;
        }).length;
    return count;
}

function remove_toc_highlighting() {
    [...K.getv(".section-title")].forEach(function (toc_item) {
        K.remove_class(toc_item, "highlight");
    });
}


function displayed_text() {
    return K.get("#text") || K.get("#search_page") || K.get("#help_page");
}
