import { world, system } from "@minecraft/server";
const levelMap = new Map();

function setPlayerLevel(player, level) {
    player.setDynamicProperty("level", level);
}

function setPlayerExp(player, exp) {
    player.setDynamicProperty("exp", exp);
}

function setPlayerDamage(player, damage) {
    player.setDynamicProperty("damage", damage);
}

function setPlayerCombo(player, combo) {
    player.setDynamicProperty("combo", combo);
}

function getPlayerLevel(player) {
    return player.getDynamicProperty("level") ?? 0;
}

function getPlayerExp(player) {
    return player.getDynamicProperty("exp") ?? 0;
}

world.afterEvents.playerJoin.subscribe((event) => {
    const player = world.getEntity(event.playerId);

    if (player.getDynamicProperty("level") === undefined) {
        setPlayerLevel(player, 0);
        setPlayerExp(player, 0);
        setPlayerDamage(player, 50);
        setPlayerCombo(player, 35);
        
        player.addTag("unlocked:sword");
        player.addTag("unlocked:axe");
    }
    const exp = getPlayerExp(player);
    const level = getPlayerLevel(player);

    levelMap.set(player.id, { level: level, exp: exp, totalExp: getExpFromLevel(level) });
});


world.afterEvents.playerBreakBlock.subscribe((event) => {
    const player = event.player;
    const exp = getPlayerExp(player);
    const level = getPlayerLevel(player);

    if (!checkRankUpLevel(player, exp, level)) {
        const newExp = exp + 1;
        setPlayerExp(player, newExp);
        levelMap.set(player.id, { level: level, exp: newExp, totalExp: getExpFromLevel(level) });
    }
})

world.afterEvents.entityDie.subscribe((event) => {
    const entity = event.deadEntity;
    const damageSource = event.damageSource;
    const player = damageSource?.damagingEntity;

    if (!player || player.typeId !== "minecraft:player") return;

    const exp = getPlayerExp(player);
    const level = getPlayerLevel(player);

    if (entity.typeId === "minecraft:warden") {
        player.sendMessage("§eYou gained +150 XP!");
        handleExpGain(player, exp, level, 150);
        return;
    }

    if (entity.typeId === "minecraft:wither") {
        player.sendMessage("§eYou gained +250 XP!");
        handleExpGain(player, exp, level, 250);
        return;
    }

    if (entity.typeId === "minecraft:ender_dragon") {
        player.sendMessage("§eYou gained +1000 XP!");
        handleExpGain(player, exp, level, 1000);
        return;
    }

    if (entity.typeId.includes("zombie") || entity.typeId.includes("skeleton") || entity.typeId.includes("spider") || entity.typeId.includes("creeper")) {
        player.sendMessage("§eYou gained +3 XP!");
        handleExpGain(player, exp, level, 3);
    } else {
        player.sendMessage("§eYou gained +1 XP!");
        handleExpGain(player, exp, level, 1);
    }
});

function handleExpGain(player, exp, level, gainedExp) {
    if (!checkRankUpLevel(player, exp, level)) {
        const newExp = exp + gainedExp;
        setPlayerExp(player, newExp);
        levelMap.set(player.id, { level: level, exp: newExp, totalExp: getExpFromLevel(level) });
    }
}

function rankUpFromLevel(player, level) {
    level = level + 1;
    switch (level) {
        case 1:
            player.addTag("unlocked:knife");
            player.setDynamicProperty("max_stamina", 90);

            player.sendMessage("§aYou leveled up to 1!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Knifes!");
            player.sendMessage("§8> §eYour Max Stamina is increased to 90!");
            break;
        case 2:
            player.setDynamicProperty("max_stamina", 100);
            player.sendMessage("§aYou leveled up to 2!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Max Stamina is increased to 100!");
            break;
        case 3:
            player.addTag("unlocked:machete");
            player.setDynamicProperty("combo", 40);
            player.sendMessage("§aYou leveled up to 3!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Damage in Combo is increased to 40%!");
            break;
        case 4:
            player.runCommandAsync("give " + player.name + " msft:small_stamina_potion 2");
            player.runCommandAsync("give " + player.name + " minecraft:diamond 2");
            player.runCommandAsync("give " + player.name + " minecraft:iron_ingot 16");

            player.sendMessage("§aYou leveled up to 4!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou received some items as a reward!");
        case 5:
            player.setDynamicProperty("damage", 10);
            player.addTag("unlocked:boomerang");

            player.sendMessage("§aYou leveled up to 5!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Boomerangs!");
            player.sendMessage("§8> §eYour damage is increased to 10%!");
            break;
        case 6:
            player.setDynamicProperty("max_stamina", 120);
            player.sendMessage("§aYou leveled up to 6!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Max Stamina is increased to 120!");
            break;
        case 7:
            player.addTag("unlocked:mace");

            player.sendMessage("§aYou leveled up to 7!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Maces!");
            break;
        case 8:
            player.sendMessage("§aYou leveled up to 8!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou received some items as a reward!");

            player.runCommandAsync("give " + player.name + " msft:small_stamina_potion 5");
            player.runCommandAsync("give " + player.name + " minecraft:diamond 3");
            player.runCommandAsync("give " + player.name + " minecraft:iron_ingot 32");
        case 9:
            player.setDynamicProperty("stamina_recovery", 5.25);

            player.sendMessage("§aYou leveled up to 9!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Stamina Recovery is increased to 5.25/s!");
            break;
        case 10:
            player.setDynamicProperty("damage", 20);

            player.sendMessage("§aYou leveled up to 10!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour damage is increased to 20%!");
            break;
        case 11:
            player.runCommandAsync("give " + player.name + " msft:small_stamina_potion 7");
            player.runCommandAsync("give " + player.name + " minecraft:diamond 6");
            player.runCommandAsync("give " + player.name + " minecraft:iron_ingot 48");

            player.sendMessage("§aYou leveled up to 11!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou received some items as a reward!");
        case 12:
            player.addTag("unlocked:dagger");

            player.sendMessage("§aYou leveled up to 12!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Daggers!");
            break;
        case 13:
            player.setDynamicProperty("combo", 40);

            player.sendMessage("§aYou leveled up to 13!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Combo Damage is increased to 40%!");
            break;
        case 14:
            player.addTag("unlocked:cutlasse");

            player.sendMessage("§aYou leveled up to 14!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Cutlasses!");
            break;
        case 15:
            player.setDynamicProperty("damage", 30);

            player.sendMessage("§aYou leveled up to 15!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour damage is increased to 30%!");
            break;
        case 16:
            player.addTag("unlocked:spear");

            player.sendMessage("§aYou leveled up to 16!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Spears!");
            break;
        case 17:
            player.setDynamicProperty("max_stamina", 140);
            player.sendMessage("§aYou leveled up to 17!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Max Stamina is increased to 140!");
            break;
        case 18:
            player.setDynamicProperty("stamina_recovery", 6.35);

            player.sendMessage("§aYou leveled up to 18!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Stamina Recovery is increased to 6.35/s!");
            break;
        case 19:
            player.addTag("unlocked:hammer");
            player.sendMessage("§aYou leveled up to 19!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Hammers!");
            break;
        case 20:
            player.setDynamicProperty("damage", 40);
            player.addTag("unlocked:heavy_crossbow");

            player.sendMessage("§aYou leveled up to 20!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Heavy CrossBows!");
            break;
        case 21:
            player.runCommandAsync("give " + player.name + " msft:small_stamina_potion 10");
            player.runCommandAsync("give " + player.name + " minecraft:diamond 10");
            player.runCommandAsync("give " + player.name + " minecraft:iron_ingot 64");

            player.sendMessage("§aYou leveled up to 21!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou received some items as a reward!");
        case 22:
            player.addTag("unlocked:scythe");

            player.sendMessage("§aYou leveled up to 22!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Scythes!");
            break;
        case 23:
            player.setDynamicProperty("combo", 45);

            player.sendMessage("§aYou leveled up to 23!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Combo Damage is increased to 45%!");
        case 24:
            player.addTag("unlocked:hammer");

            player.sendMessage("§aYou leveled up to 24!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Hammers!");
            break;
        case 25:
            player.setDynamicProperty("damage", 50);

            player.sendMessage("§aYou leveled up to 25!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour damage is increased to 50%!");
            break;
        case 26:
            player.addTag("unlocked:shuriken");
            player.sendMessage("§aYou leveled up to 26!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Shurikens!");
            break;
        case 27:
            player.runCommandAsync("give " + player.name + " msft:small_stamina_potion 2");
            player.runCommandAsync("give " + player.name + " minecraft:netherite_ingot 2");
            player.runCommandAsync("give " + player.name + " minecraft:diamond 12");

            player.sendMessage("§aYou leveled up to 27!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou received some items as a reward!");
        case 28:
            player.setDynamicProperty("max_stamina", 160);

            player.sendMessage("§aYou leveled up to 28!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Max Stamina is increased to 160!");

            break;
        case 29:
            player.addTag("unlocked:katana");

            player.sendMessage("§aYou leveled up to 29!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Katana!");
            break;
        case 30:
            player.setDynamicProperty("combo", 50);
            player.sendMessage("§aYou leveled up to 30!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Combo Damage is increased to 50%!");
        case 31:
            player.addTag("unlocked:glaives");

            player.sendMessage("§aYou leveled up to 31!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Glaives!");
            break;
        case 32:
            player.setDynamicProperty("stamina_recovery", 7.25);

            player.sendMessage("§aYou leveled up to 32!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Stamina Recovery is increased to 7.25/s!");
            break;
        case 33:
            player.setDynamicProperty("combo", 55);
            player.setDynamicProperty("max_stamina", 180);

            player.sendMessage("§aYou leveled up to 33!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Max Stamina is increased to 180!");
            player.sendMessage("§8> §eYour Combo Damage is increased to 55%!");
            break;
        case 34:
            player.addTag("unlocked:sai");

            player.sendMessage("§aYou leveled up to 34!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Sais!");
            break;
        case 35:
            player.runCommandAsync("give " + player.name + " minecraft:netherite_ingot 4");
            player.runCommandAsync("give " + player.name + " msft:echo_ingot 1");
            player.runCommandAsync("give " + player.name + " minecraft:diamond 32");
            player.runCommandAsync("give " + player.name + " minecraft:gold_ingot 32");

            player.sendMessage("§aYou leveled up to 35!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou received some items as a reward!");
        case 36:
            player.addTag("unlocked:battleaxe");

            player.sendMessage("§aYou leveled up to 36!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked BattleAxes!");
            break;
        case 37:
            player.setDynamicProperty("combo", 60);
            player.sendMessage("§aYou leveled up to 37!");
            player.sendMessage("");
            player.sendMessage("§8> §eYour Combo Damage is increased to 60%!");
        case 38:
            player.addTag("unlocked:greathammer");
            player.sendMessage("§aYou leveled up to 38!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked GreatHammers!");
            break;
        case 39:
            player.sendMessage("§aYou leveled up to 39!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked Echo Forge Crafting!");
        case 40:
            player.sendMessage("§aYou leveled up to 40!");
            player.sendMessage("");
            player.sendMessage("§8> §eYou unlocked ClayMores!");
    }
}



function getExpFromLevel(level) {
    level = level + 1;
    switch (level) {
        case 1:
            return 100;
        case 2:
            return 200;
        case 3:
            return 300;
        case 4:
            return 400;
        case 5:
            return 500;
        case 6:
            return 600;
        case 7:
            return 700;
        case 8:
            return 800;
        case 9:
            return 900;
        case 10:
            return 1000;
        case 11:
            return 1100;
        case 12:
            return 1200;
        case 13:
            return 1300;
        case 14:
            return 1400;
        case 15:
            return 1500;
        case 16:
            return 1600;
        case 17:
            return 1700;
        case 18:
            return 1800;
        case 19:
            return 1900;
        case 20:
            return 2000;
        case 21:
            return 2100;
        case 22:
            return 2200;
        case 23:
            return 2300;
        case 24:
            return 2400;
        case 25:
            return 2500;
        case 26:
            return 2600;
        case 27:
            return 2700;
        case 28:
            return 2800;
        case 29:
            return 2900;
        case 30:
            return 3000;
        case 31:
            return 3100;
        case 32:
            return 3200;
        case 33:
            return 3300;
        case 34:
            return 3400;
        case 35:
            return 3500;
        case 36:
            return 3600;
        case 37:
            return 3700;
        case 38:
            return 3800;
        case 39:
            return 3900;
        case 40:
            return 4000;

    }
}

function checkRankUpLevel(playerCheck, expCheck, levelCheck) {
    const player = playerCheck;
    const exp = expCheck;
    const level = levelCheck;
    system.run(() => {
        if (exp >= getExpFromLevel(level)) {
            const newLevel = level + 1;
            const newExp = exp - getExpFromLevel(level);

            player.runCommandAsync(`titleraw @s times 15 30 15`);
            player.runCommandAsync(`title @s title title_level_up`);
            player.runCommandAsync(`titleraw @s times 0 0 0`);
            player.playSound(`msft:ambient:level-up`);
            let location = {
                x: player.location.x + 1,
                y: player.location.y + 1.5,
                z: player.location.z
            }
            player.dimension.spawnParticle('msft_bc:lv_consumable_chained', location);
            setPlayerLevel(player, newLevel);
            setPlayerExp(player, newExp);
            rankUpFromLevel(player, level);
            levelMap.set(player.id, { level: newLevel, exp: newExp, totalExp: getExpFromLevel(level) });
            return true;
        } else {
            return false;
        }
    });
}

export { getPlayerLevel, getPlayerExp, checkRankUpLevel, setPlayerExp, getExpFromLevel, setPlayerLevel, rankUpFromLevel, levelMap };