import {MODULE_ID} from "./main.js";
import {conditionEvaluator} from "./app/Soundscapes.js";

export class RandomSoundController{
    constructor () {
        this._dirty = new Set();
        this.setPlaylist();
    }

    setPlaylist() {
        const playingPlaylist = game.settings.get(MODULE_ID, "playingPlaylist");
        this._playlist = game.playlists.get(playingPlaylist);
        this._abortSignal = Date.now();
        this.initRandomSound();
    }

    initRandomSound() {
        if (!this._playlist) return;
        const blocks = this._playlist.getFlag(MODULE_ID, "blocks") || [];
        const randomSoundBlocks = blocks.filter((block) => block.mode === "random");
        this._currentBlocks = randomSoundBlocks;
        for (const block of randomSoundBlocks) {
            this.playRandomSoundInBlock(block);
        }
    }

    updateBlocks() {
        const blocks = this._playlist.getFlag(MODULE_ID, "blocks") || [];
        const randomSoundBlocks = blocks.filter((block) => block.mode === "random");
        const newBlocks = randomSoundBlocks.filter((block) => !this._currentBlocks.some((currentBlock) => currentBlock.id === block.id));
        this._currentBlocks = randomSoundBlocks;
        for (const block of newBlocks) {
            this.playRandomSoundInBlock(block);
        }
    }

    reCheckRandomBlocks() {
        for (const block of this._currentBlocks) {
            if (this._dirty.has(block.id)) {
                this.playRandomSoundInBlock(block);
            }
        }
    }

    playRandomSoundInBlock(block) {
        const blockSounds = block.sounds;
        const sounds = blockSounds.map((soundId) => this._playlist.sounds.get(soundId)).filter((sound) => sound.flags[MODULE_ID]?.enabled);
        if (sounds.length === 0) {
            this._dirty.add(block.id);
            return;
        }
        this._dirty.delete(block.id);
        const randomSound = sounds[Math.floor(Math.random() * sounds.length)];
        const time = parseInt(block.time);
        const variance = parseFloat(block.variance);
        const minSound = time - time * variance;
        const maxSound = time + time * variance;
        const randomTime = parseInt(Math.max(2000, randomInRange(minSound, maxSound) * 1000));
        console.log(`Dynamic Soundscapes | Playing random sound ${randomSound.name} in ${randomTime / 1000}s`)
        this.playRandomSound(block, this._playlist, randomSound, randomTime);
    }

    playRandomSound(block, playlist, sound, time) {
        const startedAt = Date.now();
        setTimeout(() => {
            if (playlist !== this._playlist) return;
            if (this._abortSignal > startedAt) return;
            this.updateBlocks();
            const blocks = this._playlist.getFlag(MODULE_ID, "blocks") || [];
            const currentBlock = blocks.filter((b) => b.mode === "random").find((b) => b.id === block.id);
            if (!currentBlock) return;
            block = currentBlock;
            const isConditionMet = conditionEvaluator.evaluateCondition(block);
            if (isConditionMet) playlist.playSound(sound);
            this.playRandomSoundInBlock(block);
        }, time);
    }

}

function randomInRange(min, max) {
    return Math.random() * (max - min) + min;
}