const buttons = document.querySelectorAll("button[frame]")
const dynmapFrame = document.querySelector("article.frame.dynmap > iframe") 
const capesSelector = document.querySelector("article.capes > div.capes")
const logsContainer = document.querySelector("div.container.logs")
const playButton = document.querySelector("button.play")
const logoutButton = document.querySelector("button.logout")

let viewerInstance = new skinview3d.SkinViewer({
    canvas: document.getElementById("skin"),
    width: 390,
    height: 490,
    skin: "https://yggdrasil.azures.fr/textures/texture/steve.png"
})

viewerInstance.animation = new skinview3d.IdleAnimation()
viewerInstance.animation.speed = 1

function wait(ms) {
    return new Promise(resolve => setTimeout(resolve, ms))
}

function setActiveButton(frameIdentifier) {
    for (const button of buttons) {
        button.classList.remove("active")
        if (button.getAttribute("frame") == frameIdentifier) {
            button.classList.add("active")
        }
    }
}

function fixedTo(number, n) {
    const k = Math.pow(10, n)
    const result = (Math.round(number * k) / k)
    return Number.isInteger(result) ? result.toFixed(2) : result
}

window.getPlayer = async function getPlayer() {
    const result = await system.call("network::getPlayer")
    console.log(result)
    if (result.error) {
        console.error("Impossible de récupéré le profil")
        return null
    }
    return result
}

window.displayMinecraftHead = function displayMinecraftHead(skinUrl, targetImg) {
    const canvas = document.createElement("canvas")
    const ctx = canvas.getContext("2d")
    const skinImg = new Image()
    
    skinImg.crossOrigin = "anonymous"

    skinImg.onload = function() {
        canvas.width = 8
        canvas.height = 8

        ctx.imageSmoothingEnabled = false

        ctx.drawImage(skinImg, 8, 8, 8, 8, 0, 0, 8, 8)
        ctx.drawImage(skinImg, 40, 8, 8, 8, 0, 0, 8, 8)
        document.querySelector(targetImg).src = canvas.toDataURL()
    }

    skinImg.src = skinUrl
}

window.profile = await getPlayer()
displayMinecraftHead(`https://yggdrasil.azures.fr/textures/${profile.skins.find(skin => skin.state == "ACTIVE").url.replace(/^\//, "")}`, "img.avatar")

window.refreshProfile = async function refreshProfile() {
    window.profile = await getPlayer()
}

window.setting = {}

window.setting.set = async function settingSet(key, value) {
    await system.call("settings::set", { key, value })
}

window.showPage = function showPage(frameIdentifier) {
    showFrame(frameIdentifier)
    setActiveButton(frameIdentifier)
}

window.initDynmap = async function initDynmap() {
    const dynampUrl = await system.call("lentia::dynamp") || "http://azures.fr:8123/"
    if (dynmapFrame.src != dynampUrl) {
        dynmapFrame.src = dynampUrl
    }
}

window.getRamInformation = async function getRamInformation() {
    const $ram = await system.call("hardware::ram")
    ram.setAttribute("max", Math.floor($ram.freeGb * 1024))
    freeRam.innerText = `${$ram.totalGb} Gb`
    totalRam.innerText = `${$ram.freeGb} Gb`
}

window.handleSettingsChanges = async function handleSettingsChanges(key, value) {
    const span = document.querySelector(`span#${key.includes("ram") ? "currentRam" : key}`)
    setting.set(key, value)
    if (span) {
        span.innerText = key.includes("ram") ? fixedTo(value / 1024, 2) + " G" : value
    }
}

window.initSettings = async function initSettings() {
    const settings = await system.call("settings::read")
    ram.value = settings.ram.max
    javaPath.value = settings.javaPath
    currentRam.innerText =  fixedTo(settings.ram.max / 1024, 2) + " G"
    getRamInformation()
}

window.initSkin = async function initSkin() {
    const container = document.querySelector(".skinview3d")
    if (container.clientWidth === 0 || container.clientHeight === 0) {
        requestAnimationFrame(initSkin)
        return
    }

    const skinUrl = `https://yggdrasil.azures.fr/textures/${profile.skins.find(skin => skin.state == "ACTIVE").url.replace(/^\//, "")}`
    viewerInstance = new skinview3d.SkinViewer({
        canvas: document.getElementById("skin"),
        width: container.clientWidth,
        height: container.clientHeight,
        skin: skinUrl
    })

    displayMinecraftHead(skinUrl, "img.avatar")

    const activeCape = window.profile.capes.find(s => s.state === "ACTIVE") || null
    const capeUrl = activeCape == null ? null : `https://yggdrasil.azures.fr/textures/${activeCape.url.replace(/^\//, "")}?t=${Date.now()}`

    viewerInstance.animation = new skinview3d.IdleAnimation()
    viewerInstance.nameTag = profile.name
    viewerInstance.zoom = 0.7
    viewerInstance.loadCape(capeUrl)


    const ro = new ResizeObserver(() => {
        viewerInstance.width = container.clientWidth
        viewerInstance.height = container.clientHeight
    })

    ro.observe(container)
}

window.selectSkin = async function selectSkin() {
    const skin = await system.call("dialog::selectSkin")
    if (!skin.success) {
        return iziToast.error({ title: "Erreur", message: "Impossible d'envoyer le skin" })
    }
    return validateSkinSelection(skin.path)
}

window.validateSkinSelection = async function validateSkinSelection(localPath) {
    const isSlim = confirm("Modèle Slim ?")
    const variant = isSlim ? "slim" : "classic"

    const result = await system.call("network::uploadSkin", {
        path: localPath,
        variant: variant
    })

    if (result.success && viewerInstance) {
        await wait(500)        
        await refreshProfile()
        const activeSkin = window.profile.skins.find(s => s.state === "ACTIVE")
        const activeCape = window.profile.capes.find(s => s.state === "ACTIVE") || null

        if (activeSkin) {
            const skinUrl = `https://yggdrasil.azures.fr/textures/${activeSkin.url.replace(/^\//, "")}?t=${Date.now()}`
            const capeUrl = activeCape == null ? null : `https://yggdrasil.azures.fr/textures/${activeCape.url.replace(/^\//, "")}?t=${Date.now()}`
            displayMinecraftHead(skinUrl, "img.avatar")
            await viewerInstance.loadSkin(skinUrl, {
                model: variant.toLowerCase() === "slim" ? "slim" : "default"
            })
            await viewerInstance.loadCape(capeUrl)
        }
    }
}

window.initCapesSelector = async function initCapesSelector() {
    capesSelector.innerHTML = ""
    const blankCape = document.createElement("div")
    blankCape.classList.add("cape")
    blankCape.setAttribute("onclick", `hideCape()`)
    blankCape.title = "Cacher ma cape"
    capesSelector.appendChild(blankCape)
    await viewerInstance.loadCape(null)
    for (const cape of profile.capes) {
        const $cape = document.createElement("div")
        $cape.classList.add("cape")
        $cape.setAttribute("title", cape.alias)
        $cape.setAttribute("style", `background-image: url("https://yggdrasil.azures.fr/textures/${cape.url.replace(/^\//, "")}?t=${Date.now()}") !important;`)
        $cape.setAttribute("onclick", `showCape("${cape.id}")`)
        if (cape.state == "ACTIVE") {
            $cape.classList.add("active")
            await viewerInstance.loadCape(`https://yggdrasil.azures.fr/textures/${cape.url.replace(/^\//, "")}?t=${Date.now()}`)
        }
        capesSelector.appendChild($cape)
    }
}

window.showCape = async function showCape(id) {
    const result = await system.call("network::showCape", { capeId: id })

    if (result.success) {
        await refreshProfile()
        await initCapesSelector()

        if (typeof viewerInstance !== "undefined" && window.profile) {
            const activeCape = window.profile.capes.find(c => c.state === "ACTIVE")
            if (activeCape) {
                const fullUrl = `https://yggdrasil.azures.fr/textures/${activeCape.url.replace(/^\//, "")}?t=${Date.now()}`
                await viewerInstance.loadCape(fullUrl)
            }
        }

        return result.data
    } else {
        alert("Erreur d'équipement : " + result.error)
    }
}

window.hideCape = async function hideCape() {
    const result = await system.call("network::hideCape")

    if (result.success) {
        await refreshProfile()
        await initCapesSelector()
        
        if (typeof viewerInstance !== "undefined") {
            viewerInstance.loadCape(null)
        }

        return result.data
    } else {
        alert("Erreur lors du retrait : " + result.error)
    }
}

window.changeUsername = async function changeUsername(newName) {
    if (!newName || newName.length < 3) return alert("Pseudo trop court !");

    const result = await system.call("network::changeUsername", {
        username: newName
    })

    if (result.success) {
        viewerInstance.nameTag = result.profile.name
        window.profile = result.profile
    } else {
        alert("Erreur : " + result.error)
    }
}

window.gamelog = {}

window.gamelog.put = function put(log) {
    const logElement = document.createElement("p")
    logElement.innerText = log
    logsContainer.appendChild(logElement)
}

window.gamelog.clear = function clear() {
    logsContainer.innerHTML = ""
}

window.play = async function play() {
    gamelog.clear()
    showLoadingBar()
    playButton.setAttribute("disabled", "")
    logoutButton.setAttribute("disabled", "")
    const gameLaunch = await system.call("launcher::game")
    if (gameLaunch.success) {
        hideLoadingBar()
    } else {
        hideLoadingBar()
        playButton.removeAttribute("disabled")
        logoutButton.removeAttribute("disabled")
    }
}

window.external.receiveMessage(message => {
    try {
        const data = JSON.parse(message)
        
        switch (data.requestId) {
            case "game::log":
                const logMessage = data.payload.message
                if (logMessage != "GAME_CLOSED") {                    
                    console.log("MC:", logMessage)
                    gamelog.put(logMessage)
                    logsContainer.scrollTop = logsContainer.scrollHeight
                } else {
                    playButton.removeAttribute("disabled")
                }
                break;
        
            default:
                break;
        }
    } catch (e) {
        console.error("Erreur réception message Photino:", e)
    }
})

await initSkin()
await initSettings()
await initCapesSelector()
hideLoadingBar()
showFrame("game")