import { ActionFormData } from "@minecraft/server-ui";
import { system, world } from "@minecraft/server";
import * as utils from "../utils";
import * as inventory_utils from "../inventory_utils";
import * as gld from "../gld";
import * as wallet from "../wallet";
import { showApp as main_menu, checkDepletedBattery } from "./main_menu"; 
import { showApp as finances } from "./bank";

const playMusicName = gld.getAppData("play_music");

export async function showApp(player){
    if (await checkDepletedBattery(player))
        return;

    //The Dynamic Property keeps a string in this form song1:song2:song3: etc
    let playerSongs = player.getDynamicProperty("goe_spa_music").split(':').filter(song => song !== '');
    if(playerSongs.length === 0) {
        let freeSongs = gld.songs.filter(song => song.cost === 0).map(song => song.name);
        freeSongs.forEach(song => {
            playerSongs.push(song);
        });
    }

    let currentlyPlaying = "";
    if (player.getDynamicProperty("goe_spa_is_music_playing")) {
        const songName = player.getDynamicProperty("goe_spa_currently_playing");
        currentlyPlaying = `§eCurently playing: §r${utils.toTitleCase(songName)}\n\n`;
    }


    const PlayerMusicApp = new ActionFormData()
        .title(`${playMusicName.name}`)
        .body(
            gld.getScreenTitle(player) +
            "Use this app to listen to some cool new music.\n\n" +
            `${currentlyPlaying}` +
            `Select music to play:`
        );

    playerSongs.forEach(song => {
        PlayerMusicApp.button(`§aPlay: §d${song}`, "textures/goe/spa/ui/play_music_start");
    });

    PlayerMusicApp
        .button("§6Buy more music", "textures/goe/spa/ui/play_music")
        .button("§cStop music", "textures/goe/spa/ui/stop_music")
        .button("Back", "textures/goe/spa/ui/back");

    PlayerMusicApp.show(player).then((response) => {
        inventory_utils.replacePhoneIfUIClosed(player, response);
        let playerPressed = response.selection;

        player.playSound("goe_spa:button_click");
        if (playerPressed < playerSongs.length) {
            playSong(playerSongs[playerPressed], player, true);
        } else {
            switch(playerPressed - playerSongs.length) {
                case 0:
                    buyMoreMusic(player, playerSongs);
                    break;
                case 1:
                    stopMusic(player);
                    break;
                case 2:
                    main_menu(player)
                    break;
            }
        }
    });
}

async function playSong(songName, player, calledFromForm) {
    
    songName = utils.toSnakeCase(songName);
    //First stop the sounds to not play multiple at once
    utils.runPlayerCommand(player, "stopsound @s");
    player.setDynamicProperty("goe_spa_is_music_playing", true);
    player.setDynamicProperty("goe_spa_tick_it_started", system.currentTick);
    player.setDynamicProperty("goe_spa_currently_playing", songName);

    // Play music
    player.runCommandAsync(`playsound goe_spa:music_${songName} @s`);
    if(calledFromForm)
        showApp(player);
}

export async function onTick() {
    for(let player of world.getAllPlayers()) {
        if (player === undefined)
            continue;
        if(player.getDynamicProperty("goe_spa_is_music_playing")){
            player.runCommandAsync("stopsound @s game");
            let tickItStared = player.getDynamicProperty("goe_spa_tick_it_started");
            let songName = player.getDynamicProperty("goe_spa_currently_playing");
            let song = gld.songs.find(song => song.name.toLowerCase() === songName.toLowerCase());
            if((system.currentTick - tickItStared) === song.duration) {
                await playSong(songName, player, false);
            }
            
        }
    }
}

async function buyMoreMusic(player, playerSongs) {
    let coins = await player.getDynamicProperty("goe_spa_coins");

    let filteredSongs = [];
    let playerSongsSet = [];

    if(playerSongs.length !== 0){
        playerSongsSet = new Set(playerSongs);
        filteredSongs = gld.songs.filter(song => !playerSongsSet.has(song.name));
    } else {
        filteredSongs = gld.songs;
    }

    let allMusicBoughtMsg = "All music tracks have been purchased, play them and enjoy the sound.\n\n" +
        "§5Don't forget to give this Add-On a 5-star rating on the Marketplace.\n"+
        "§6               ⭐⭐⭐⭐⭐"
    let buyMusic = new ActionFormData().title(`${playMusicName.name}`);
    let bodyText = gld.getScreenTitle(player);
    bodyText += (filteredSongs.length === 0) ? allMusicBoughtMsg : "Available tracks for purchase:";
    buyMusic.body(bodyText);
    
    filteredSongs.forEach(song => {
        let costColor = wallet.canAfford(player, song.cost) ? "§l§a" : "§l§c";
        buyMusic.button(`§l§d${song.name}\n${costColor}Cost: ${song.cost} ${gld.coinSymbol}`);
    });

    buyMusic.button("Back", "textures/goe/spa/ui/back");

    buyMusic.show(player).then((response) => {
        inventory_utils.replacePhoneIfUIClosed(player, response);
        let playerPressed = response.selection;

        player.playSound("goe_spa:button_click");
        if (playerPressed < filteredSongs.length) {
            buySong(filteredSongs[playerPressed], player, coins, playerSongs);
        } else {
            switch(playerPressed - filteredSongs.length) {
                case 0:
                    showApp(player)
                    break;
            }
        }
    });
}

async function buySong(song, player, coins, playerSongs) {
    
    const songValue = song.cost;

    try {
        if(wallet.canAfford(player, songValue)) {
            player.playSound("goe_spa:purchase");
            // player.setDynamicProperty("goe_spa_coins", coins-songValue);
            playerSongs.push(song.name);
            player.setDynamicProperty("goe_spa_music", playerSongs.join(':'));
            utils.tellraw(player, "@s", `Purchashed music: ${song.name}`);
            // utils.tellraw(player, "@s", `§aSmartcoins balance: ${wallet.getBalance(player)}`);

            player.dimension.spawnParticle("goe_spa:music_notes", player.location);

            wallet.charge(player, songValue);
            
        } else {
            player.playSound("goe_spa:reject");
            showCantAffordMessage(player, song, playerSongs);
            return;
        }
    } catch (error) {
        utils.runPlayerCommand(player,"title @s actionbar §cTransaction failed. Please try again.");
    }
    showApp(player);
}

async function showCantAffordMessage(player, song, playerSongs){
    const CantAffordForm = new ActionFormData()
        .title(`${playMusicName.name}`)
        .body(
            gld.getScreenTitle(player) +
            `\nNot enough Smartcoins (§6${gld.coinSymbol}§r)\n\n` +
            `§d${song.name}\n\n`+
            `§cCost: ${song.cost} ${gld.coinSymbol}\n`+
            `§4Missing: ${Math.abs(wallet.getBalance(player)-song.cost)} ${gld.coinSymbol}\n\n`
        )
        .button("§eGet Smartcoins", gld.getAppData("bank").icon)
        .button("Back", "textures/goe/spa/ui/back");

        CantAffordForm.show(player).then((response) => {
        inventory_utils.replacePhoneIfUIClosed(player, response);
        player.playSound("goe_spa:button_click");
        let playerPressed = response.selection;
        switch(playerPressed) {
            case 0:
                finances(player);
                break;

            case 1:
                buyMoreMusic(player, playerSongs)
                break;
        }
    });
}

export async function stopMusic(player, openApp) {
    player.runCommandAsync("stopsound @s");
    player.setDynamicProperty("goe_spa_is_music_playing", false);
    if (openApp !== false)
        showApp(player);
}