import { anthill } from "./anthill.js";
import { sound } from "./sound.js";

const MIN_TRACK_INDEX = 1;
const MAX_TRACK_INDEX = 5;
const TRACK_PATHS = {
    1: "assets/music/1.mp3",
    2: "assets/music/2.mp3",
    3: "assets/music/3.mp3",
    4: "assets/music/4.mp3",
    5: "assets/music/5.mp3"
};

export class Music {
    constructor(options = {}) {
        this.maxVolume = this.normalizeVolume(options.maxVolume, 1);
        this.initialVolume = this.normalizeVolume(options.initialVolume, 0.5);
        this.isUnlocked = false;
        this.currentTrackIndex = this.resolveTrackIndex();
        this.activeAudio = null;
        this.tracks = this.createTracks();

        sound.setInitialVolume(this.initialVolume);
        this.applyVolume(sound.getVolume());
        sound.addChangeListener(volume => {
            this.applyVolume(volume);
        });
    }

    normalizeVolume(value, fallbackValue) {
        const normalizedValue = Number.isFinite(value) ? value : fallbackValue;
        return Math.min(1, Math.max(0, normalizedValue));
    }

    createTracks() {
        const tracks = {};

        for (let trackIndex = MIN_TRACK_INDEX; trackIndex <= MAX_TRACK_INDEX; trackIndex += 1) {
            const audio = new Audio(TRACK_PATHS[trackIndex]);
            audio.loop = true;
            audio.preload = "auto";
            tracks[trackIndex] = audio;
        }

        return tracks;
    }

    unlock() {
        if (this.isUnlocked) {
            return false;
        }

        this.isUnlocked = true;
        this.playCurrentTrack();
        return true;
    }

    resolveTrackIndex() {
        const unlockedAntCount = anthill.getUnlockedAntCount();
        return Math.min(MAX_TRACK_INDEX, Math.max(MIN_TRACK_INDEX, unlockedAntCount || MIN_TRACK_INDEX));
    }

    applyVolume(volume) {
        const effectiveVolume = sound.getScaledVolume(this.maxVolume);

        for (const audio of Object.values(this.tracks)) {
            audio.volume = effectiveVolume;
        }
    }

    setMaxVolume(value) {
        this.maxVolume = this.normalizeVolume(value, this.maxVolume);
        this.applyVolume(sound.getVolume());
        return this.maxVolume;
    }

    playCurrentTrack() {
        if (!this.isUnlocked) {
            return;
        }

        const nextAudio = this.tracks[this.currentTrackIndex];
        if (!nextAudio) {
            return;
        }

        if (this.activeAudio === nextAudio) {
            if (nextAudio.paused) {
                nextAudio.play().catch(() => {
                    return;
                });
            }
            return;
        }

        if (this.activeAudio) {
            this.activeAudio.pause();
            this.activeAudio.currentTime = 0;
        }

        this.activeAudio = nextAudio;
        this.activeAudio.currentTime = 0;
        this.activeAudio.play().catch(() => {
            return;
        });
    }

    update() {
        const nextTrackIndex = this.resolveTrackIndex();
        if (nextTrackIndex === this.currentTrackIndex) {
            return;
        }

        this.currentTrackIndex = nextTrackIndex;
        this.playCurrentTrack();
    }
}

export const music = new Music({
    initialVolume: 0.5,
    maxVolume: 0.1
});