// Emoji zoom-in functionality.

import { addSpell } from "treehouse/spells.js";

class EmojiTooltip extends HTMLElement {
    constructor(emoji, element, { onClosed }) {
        super();

        this.emoji = emoji;
        this.emojiElement = element;
        this.onClosed = onClosed;
    }

    connectedCallback() {
        this.role = "tooltip";

        this.image = new Image();
        this.image.src = this.emojiElement.src;

        this.description = document.createElement("p");
        this.description.textContent = `${this.emoji.emojiName}`;

        let emojiBoundingBox = this.emojiElement.getBoundingClientRect();
        this.style.left = `${emojiBoundingBox.left + emojiBoundingBox.width / 2}px`;
        this.style.top = `calc(${emojiBoundingBox.top}px + 1.5em)`;

        this.fullyOpaque = false;
        this.addEventListener("transitionend", event => {
            if (event.propertyName == "opacity") {
                this.fullyOpaque = !this.fullyOpaque;
                if (!this.fullyOpaque) {
                    this.onClosed();
                }
            }
        });
        // Timeout is zero because we just want to execute this later, to be definitely sure
        // the transition plays out.
        setTimeout(() => this.classList.add("transitioned-in"), 0);

        this.appendChild(this.image);
        this.appendChild(this.description);
    }

    close() {
        this.classList.remove("transitioned-in");
    }
}

customElements.define("th-emoji-tooltip", EmojiTooltip);

let emojiTooltips = null;

class EmojiTooltips extends HTMLElement {
    constructor() {
        super();
        this.tooltips = new Set();
        this.abortController = new AbortController();
    }

    connectedCallback() {
        emojiTooltips = this;

        addEventListener(
            "wheel",
            event => emojiTooltips.closeTooltips(event),
            { signal: this.abortController.signal },
        );
    }

    disconnectedCallback() {
        this.abortController.abort();
    }

    openTooltip(emoji, element) {
        let tooltip = new EmojiTooltip(emoji, element, {
            onClosed: () => {
                this.removeChild(tooltip);
                this.tooltips.delete(tooltip);
            },
        });

        this.appendChild(tooltip);
        this.tooltips.add(tooltip);

        return tooltip;
    }

    closeTooltip(tooltip) {
        tooltip.close();
    }

    closeTooltips() {
        for (let tooltip of this.tooltips) {
            tooltip.close();
        }
    }
}

customElements.define("th-emoji-tooltips", EmojiTooltips);

class Emoji {
    constructor(element) {
        this.emojiName = element.title;

        // title makes the browser add a tooltip. We replace browser tooltips with our own,
        // so remove the title.
        element.title = "";

        element.addEventListener("mouseenter", () => this.openTooltip(element));
        element.addEventListener("mouseleave", () => this.closeTooltip());
        element.addEventListener("scroll", () => this.closeTooltip());
    }

    openTooltip(element) {
        this.tooltip = emojiTooltips.openTooltip(this, element);
    }

    closeTooltip() {
        emojiTooltips.closeTooltip(this.tooltip);
        this.tooltip = null;
    }
}

addSpell("emoji", Emoji);