// retoor <retoor@molodetz.nl>

import { Http } from "./Http.js";
import { Avatar } from "./Avatar.js";
import { TextInput } from "./TextInput.js";
import { DomUtils } from "./DomUtils.js";
import { ListNav } from "./ListNav.js";

export class MentionInput {
    constructor(element) {
        this.input = element;
        this.dropdown = null;
        this.debounceTimer = null;
        this.lastMatch = null;
        this.nav = null;
        this.build();
    }

    build() {
        const wrap = document.createElement("div");
        wrap.className = "mention-wrapper";
        this.input.parentNode.insertBefore(wrap, this.input);
        wrap.appendChild(this.input);

        this.dropdown = document.createElement("div");
        this.dropdown.className = "mention-dropdown";
        this.dropdown.setAttribute("role", "listbox");
        wrap.appendChild(this.dropdown);

        this.nav = new ListNav(this.input, this.dropdown, {
            itemSelector: ".mention-dropdown-item",
            activeClass: "active",
            isOpen: () => DomUtils.isShown(this.dropdown),
            onChoose: (item) => this.insert(item.dataset.username),
            onEscape: () => this.hide(),
        });

        this.input.addEventListener("input", () => this.onInput());
        this.input.addEventListener("blur", () => {
            setTimeout(() => this.hide(), 200);
        });
    }

    hide() {
        DomUtils.hide(this.dropdown);
        this.nav.closed();
    }

    onInput() {
        clearTimeout(this.debounceTimer);
        const pos = this.input.selectionStart;
        const text = this.input.value.substring(0, pos);
        let match = text.match(/(?:^|\s|\x28)@([a-zA-Z0-9_-]*)$/);

        if (!match) {
            this.hide();
            this.lastMatch = null;
            return;
        }

        const query = match[1];
        this.lastMatch = { query, index: match.index + (text[match.index] === "@" ? 0 : 1) };

        if (query.length < 1) {
            this.hide();
            return;
        }

        this.debounceTimer = setTimeout(() => this.fetch(query), 200);
    }

    async fetch(query) {
        try {
            const data = await Http.getJson("/profile/search?q=" + encodeURIComponent(query));
            const results = data.results || [];
            if (results.length === 0) {
                this.hide();
                return;
            }
            this.render(results);
        } catch (e) {
            this.hide();
        }
    }

    render(results) {
        this.dropdown.innerHTML = "";
        for (const r of results) {
            const item = document.createElement("button");
            item.type = "button";
            item.className = "mention-dropdown-item";
            item.dataset.username = r.username;
            const label = document.createElement("span");
            label.textContent = "@" + r.username;
            item.append(Avatar.imgElement(r.username), label);
            item.addEventListener("mousedown", (e) => {
                e.preventDefault();
                this.insert(r.username);
            });
            this.dropdown.appendChild(item);
        }
        DomUtils.show(this.dropdown);
        this.nav.opened();
    }

    insert(username) {
        if (!this.lastMatch) return;
        const val = this.input.value;
        let before = val.substring(0, this.lastMatch.index);
        let after = val.substring(this.lastMatch.index + this.lastMatch.query.length + 1);
        before = before.replace(/@+$/, "");
        after = after.replace(/^@+/, "");
        TextInput.applyValue(this.input, before + "@" + username + " " + after, before.length + username.length + 2);
        this.hide();
        this.lastMatch = null;
    }
}
window.MentionInput = MentionInput;
