const MODULE_PATH = `modules/tidbits/assets/system-tidbits`;

export class Tidbits {
    constructor() {
        this.tidbits = [];
        this._originalTidbits = [];
        this.imageTidbits = [];
        this._ready = false;
        this.converter = new showdown.Converter();
        this.initLoadingScreen();
        this.activateListeners();
        this._resolveLoaded;
        this._loadingStatus = new Promise((resolve, reject) => {
            this._resolveLoaded = resolve;
        });
    }

    async loadSources() {
        let systemTidbits = [];
        try {
            if (game.settings.get("tidbits", "useDefaultSources")) {
                systemTidbits = await foundry.utils.fetchJsonWithTimeout(`${MODULE_PATH}/${game.system.id.toLowerCase()}.json`);
            }
        } catch (error) {}
        let customTidbits = [];
        const customPath = game.settings.get("tidbits", "customSource") ?? "";
        const isJson = customPath.toLowerCase().endsWith(".json");
        try {
            if (isJson) {
                customTidbits = await foundry.utils.fetchJsonWithTimeout(game.settings.get("tidbits", "customSource"));
            } else if (customPath) {
                const response = await fetch(game.settings.get("tidbits", "customSource"));
                const resText = (await response.text()) ?? "";
                //split on new lines
                customTidbits = resText.split(/\r?\n/);
                customTidbits = customTidbits.filter((t) => t);
            }
        } catch (error) {}
        this.tidbits = systemTidbits.concat(customTidbits);
        this._originalTidbits = [...this.tidbits];
        let imageTidbits = [];
        try {
            if (game.user.isGM) {
                const fp = new foundry.applications.apps.FilePicker.implementation({current: game.settings.get("tidbits", "imageSource")});
                const source = fp.activeSource;
                const dir = fp.target;
                const contents = await foundry.applications.apps.FilePicker.implementation.browse(source, dir);
                imageTidbits = [...contents.files];
                game.settings.set("tidbits", "imagePaths", imageTidbits);
            } else {
                imageTidbits = game.settings.get("tidbits", "imagePaths");
            }
        } catch (error) {}
        this.imageTidbits = imageTidbits;
        this._ready = true;
        this._resolveLoaded(true);
        this.getStartupTidbit();
        this.getStartupLoadingScreen();
        this.setPausedText();
    }

    async activateListeners() {
        $(document).on("click", ".reroll-tidbit", (e) => {
            const messageLi = e.currentTarget.closest(".chat-message");
            const message = game.messages.get(messageLi.dataset.messageId);
            const content = this.getTidbitMessageContent();
            if (content) {
                message.update({ content });
            }
        });
        $(document).on("click", "#tidbits-loading-screen .fa-lightbulb-exclamation-on", (e) => {
            this.showLoadingScreen(true);
        });
    }

    getStartupTidbit() {
        if (!this.processChoice(game.settings.get("tidbits", "showChatMessage"))) return;
        const oldTidbits = Array.from(game.messages)
            .filter((m) => m.flags?.tidbits?.isTidbit && m.author.id == game.user.id)
            .map((m) => m.id);
        ChatMessage.deleteDocuments(oldTidbits);
        const content = this.getTidbitMessageContent();
        if (content) {
            ChatMessage.create({
                content,
                speaker: { alias: game.i18n.localize("tidbits.message.tidbits") },
                whisper: [game.user.id],
                flags: { tidbits: { isTidbit: true } },
            });
        }
    }

    getTidbitMessageContent() {
        const tidbit = this.get(true);
        if (!tidbit) return;
        return `
        <div class="tidbit-content">
            <h3>
            <i class="fa-duotone fa-lightbulb-exclamation-on"></i>
            <div class="tidbit-text">
            ${this.getDidYouKnowText()}
            </div>
            <i class="reroll-tidbit fa-duotone fa-dice"></i>
            </h3>
        ${tidbit}
        </div>`;
    }

    getStartupLoadingScreen() {
        const startupTidbitTime = game.settings.get("tidbits", "startupLoadingScreen");
        if (!startupTidbitTime) return;
        this.showLoadingScreen();
        setTimeout(() => {
            this.hideLoadingScreen();
        }, startupTidbitTime * 1000);
    }

    processChoice(choice) {
        if (choice == "everyone") return true;
        if (choice == "players" && !game.user.isGM) return true;
        if (choice == "gamemaster" && game.user.isGM) return true;
        return false;
    }

    get() {
        if (!this.tidbits.length) this.tidbits = [...this._originalTidbits];
        if (!this.tidbits.length) return "";
        let tidbit = this.tidbits[Math.floor(Math.random() * this.tidbits.length)];
        this.tidbits.splice(this.tidbits.indexOf(tidbit), 1);
        tidbit = this.converter.makeHtml(tidbit);
        return tidbit;
    }

    getImage() {
        if (this.imageTidbits.length && game.settings.get("tidbits", "imageSource")) {
            const image = this.imageTidbits[Math.floor(Math.random() * this.imageTidbits.length)];
            return image;
        } else {
            return "";
        }
    }

    getDidYouKnowText() {
        const custom = game.settings.get("tidbits", "didYouKnowText");
        return custom || game.i18n.localize("tidbits.message.didYouKnow");
    }

    initLoadingScreen() {
        const loadingScreen = document.createElement("div");
        //close on right click
        loadingScreen.addEventListener("contextmenu", (e) => {
            e.preventDefault();
            this.hideLoadingScreen();
        });
        loadingScreen.id = "tidbits-loading-screen";
        loadingScreen.classList.add("hidden");
        loadingScreen.innerHTML = `
        <div class="loading-screen">
            <div class="loading-screen-content">
                <h1><i class="fa-duotone fa-lightbulb-exclamation-on"></i> ${this.getDidYouKnowText()}</h1>
                <p class="loading-screen-text"></p>
            </div>
            <div class="loading-screen-background"></div>
        </div>`;
        document.body.appendChild(loadingScreen);
        this.loadingScreen = loadingScreen;
        this.loadingScreenText = loadingScreen.querySelector(".loading-screen-text");
        this.loadingScreenContent = loadingScreen.querySelector(".loading-screen-content");
        this.loadingScreenBackground = loadingScreen.querySelector(".loading-screen-background");
    }

    async showLoadingScreen(force = false) {
        if (!this.processChoice(game.settings.get("tidbits", "showLoadingScreen"))) return;
        if (!force && this._showingLoadingScreen) return;
        this._showingLoadingScreen = true;
        this.loadingScreenBackground.classList.toggle("clean", !game.settings.get("tidbits", "loadingScreenGradient"));
        this.loadingScreen.classList.remove("hidden");
        const text = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.get(true));
        if (!this._ready) {
            this._loadingStatus.then(() => {
                this.loadingScreenText.innerHTML = text;
                this.loadingScreenBackground.style.backgroundImage = `url(${this.getImage()})`;
            });
        }
        this.loadingScreenBackground.style.backgroundImage = `url(${this.getImage()})`;
        this.loadingScreenText.innerHTML = text;
        const offset = document.getElementById("sidebar").offsetWidth - document.getElementById("controls").offsetWidth;
        this.loadingScreenContent.style.marginLeft = `-${offset}px`;
    }

    hideLoadingScreen() {
        if (this._fadingOut) return;
        this._fadingOut = true;

        const delay = game.settings.get("tidbits", "loadingScreenMinimumDuration") * 1000 - 1000;
        const duration = 1000;

        //fade out animation
        this.loadingScreen.animate([{ opacity: 1 }, { opacity: 0 }], {
            delay: delay,
            duration: duration,
            easing: "ease-in-out",
        });

        setTimeout(() => {
            this._showingLoadingScreen = false;
            this._fadingOut = false;
            this.loadingScreen.classList.add("hidden");
            this.loadingScreenText.innerHTML = "";
        }, delay + duration);
    }

    async setPausedText() {
        if (!game.settings.get("tidbits", "pauseText")) return;
        const pauseEl = document.getElementById("pause");
        if(!pauseEl) return;
        const textContainer = pauseEl.querySelector("figcaption")

        const text = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.get(true));

        if (!this._ready) {
            this._loadingStatus.then(() => {
                textContainer.innerHTML = `<div class="tidbit-pause-text">${text}</div>`;
            });
        } else {
            textContainer.innerHTML = `<div class="tidbit-pause-text">${text}</div>`;
        }

        const autoCycle = game.settings.get("tidbits", "autoCycle");
        
        if (autoCycle && !this._timerRunning) {
            this._timerRunning = true;
            setTimeout(() => {
                this._timerRunning = false;
                this.setPausedText();
            }, autoCycle * 1000);
        }
    }
}
