import Core from "evite/src/core"
import { Howl } from "howler"
import config from "config"
import axios from "axios"
import store from "store"

export default class SoundCore extends Core {
    static namespace = "sound"

    soundsPool = {}

    public = {
        play: this.play.bind(this),
        loadSoundpack: this.loadSoundpack.bind(this),
        useUIAudio: function (audio_id) {
            try {
                if (window.app.cores.settings.is("ui.effects", true)) {
                    this.play(audio_id)
                }
            } catch (error) {
                this.console.error(error)
            }
        }.bind(this)
    }

    listenEvents = {
        "change:app.general_ui_volume": (volume) => {
            // play a sound to test volume
            this.play("test", {
                volume: volume / 100,
            })
        }
    }

    async loadSoundpack(manifest) {
        let soundpack = config.defaultSoundPack ?? {}

        const storedCustomSoundpack = manifest ?? store.get("soundpack_manifest")

        if (storedCustomSoundpack) {
            // check if is valid url with regex
            const urlRegex = /^(ftp|http|https):\/\/[^ "]+$/;

            if (urlRegex.test(storedCustomSoundpack)) {
                // load with axios
                const { data } = await axios.get(storedCustomSoundpack)

                soundpack = data
            } else {
                this.console.error(`Soundpack [${storedCustomSoundpack}] is not a valid url.`)
                return false
            }
        }

        if (typeof soundpack.sounds !== "object") {
            this.console.error(`Soundpack [${soundpack.id}] is not a valid soundpack.`)
            return false
        }

        this.console.log(`Loading soundpack [${soundpack.id} | ${soundpack.name}] by ${soundpack.author} (${soundpack.version})`)

        for (const [name, path] of Object.entries(soundpack.sounds)) {
            this.soundsPool[name] = new Howl({
                volume: 0.5,
                src: [path],
            })
        }
    }

    async injectUseUIAudio() {
        const injectOnButtons = (event) => {
            // search for closest button
            const button = event.target.closest("button") || event.target.closest(".ant-btn")

            // if button exist and has aria-checked attribute then play switch_on or switch_off
            if (button) {
                if (button.hasAttribute("aria-checked")) {
                    return this.public.useUIAudio(button.getAttribute("aria-checked") === "true" ? "component.slider_down" : "component.slider_up")
                }

                return this.public.useUIAudio("generic_click")
            }
        }

        document.addEventListener("click", (event) => {
            injectOnButtons(event)
        }, true)
    }

    async play(name, options = {}) {
        const audioInstance = this.soundsPool[name]

        if (!audioInstance) {
            this.console.error(`Sound [${name}] not found or is not available.`)
            return false
        }

        if (typeof options.volume !== "undefined") {
            audioInstance.volume(options.volume)
        } else {
            audioInstance.volume((window.app.cores.settings.get("ui.general_volume") ?? 0) / 100)
        }

        audioInstance.play()
    }

    async onInitialize() {
        await this.loadSoundpack()

        // listen eventBus
        for (const [eventName, callback] of Object.entries(this.listenEvents)) {
            window.app.eventBus.on(eventName, callback)
        }

        this.injectUseUIAudio()
    }
}