export class MentionInput {
    constructor(element) {
        this.input = element;
        this.dropdown = null;
        this.debounceTimer = null;
        this.selectedIndex = -1;
        this.lastMatch = 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";
        wrap.appendChild(this.dropdown);

        this.input.addEventListener("input", () => this.onInput());
        this.input.addEventListener("keydown", (e) => this.onKeydown(e));
        this.input.addEventListener("blur", () => {
            setTimeout(() => { this.dropdown.style.display = "none"; }, 200);
        });
    }

    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.dropdown.style.display = "none";
            this.lastMatch = null;
            return;
        }

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

        if (query.length < 1) {
            this.dropdown.style.display = "none";
            return;
        }

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

    async fetch(query) {
        try {
            const resp = await fetch("/profile/search?q=" + encodeURIComponent(query));
            const data = await resp.json();
            const results = data.results || [];
            if (results.length === 0) {
                this.dropdown.style.display = "none";
                return;
            }
            this.render(results);
        } catch (e) {
            this.dropdown.style.display = "none";
        }
    }

    render(results) {
        this.dropdown.innerHTML = "";
        this.selectedIndex = -1;
        for (const r of results) {
            const item = document.createElement("button");
            item.type = "button";
            item.className = "mention-dropdown-item";
            item.dataset.username = r.username;
            item.innerHTML = '<img src="/avatar/multiavatar/' + encodeURIComponent(r.username) + '?size=24" class="avatar-img" style="width:24px;height:24px;border-radius:50%" alt="" loading="lazy"><span>@' + r.username + '</span>';
            item.addEventListener("mousedown", (e) => {
                e.preventDefault();
                this.insert(r.username);
            });
            this.dropdown.appendChild(item);
        }
        this.dropdown.style.display = "block";
    }

    onKeydown(e) {
        const items = this.dropdown.querySelectorAll(".mention-dropdown-item");
        if (this.dropdown.style.display !== "block" || items.length === 0) {
            return;
        }

        if (e.key === "ArrowDown") {
            e.preventDefault();
            this.selectedIndex = Math.min(this.selectedIndex + 1, items.length - 1);
            this.highlight(items);
        } else if (e.key === "ArrowUp") {
            e.preventDefault();
            this.selectedIndex = Math.max(this.selectedIndex - 1, 0);
            this.highlight(items);
        } else if (e.key === "Enter" || e.key === "Tab") {
            if (this.selectedIndex >= 0 && items[this.selectedIndex]) {
                e.preventDefault();
                this.insert(items[this.selectedIndex].dataset.username);
            }
        } else if (e.key === "Escape") {
            this.dropdown.style.display = "none";
        }
    }

    highlight(items) {
        items.forEach((item, i) => {
            item.classList.toggle("active", i === this.selectedIndex);
        });
        if (this.selectedIndex >= 0 && items[this.selectedIndex]) {
            items[this.selectedIndex].scrollIntoView({ block: "nearest" });
        }
    }

    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(/^@+/, "");
        this.input.value = before + "@" + username + " " + after;
        const newPos = before.length + username.length + 2;
        this.input.setSelectionRange(newPos, newPos);
        this.input.focus();
        this.input.dispatchEvent(new Event("input", { bubbles: true }));
        this.dropdown.style.display = "none";
        this.lastMatch = null;
    }
}
window.MentionInput = MentionInput;
