import { world, system } from '@minecraft/server';
import * as game from "./game";

const effects = {
    helmet: { type: "saturation", amplifier: 0 },
    chestplate: { type: "absorption", amplifier: 0 },
    leggings: { type: "health_boost", amplifier: 0 },
    boots: { type: "speed", amplifier: 0 },
    fullArmor1: { type: "resistance", amplifier: 0 },
    fullArmor2: { type: "fire_resistance", amplifier: 0 }
}

export async function onTick() {
    const players = world.getAllPlayers();
    for (const player of players) {
        const hasHelmet = await handleHelmet(player);
        const hasChestplate = await handleChestplate(player);
        const hasLeggings = await handleLeggings(player);
        const hasBoots = await handleBoots(player);

        const hadFullArmor = player.getDynamicProperty("tcs_ohs_has_full_armor");
        const hasFullArmor = hasHelmet && hasChestplate && hasLeggings && hasBoots;
        const effectsPresent = await hasEffect(player, effects.fullArmor1) && await hasEffect(player, effects.fullArmor2);

        if (!hasFullArmor) {
            if (hadFullArmor && effectsPresent) {
                removeEffect(player, effects.fullArmor1);
                removeEffect(player, effects.fullArmor2);
            }   

            player.setDynamicProperty("tcs_ohs_has_full_armor", false);
        } else if (!effectsPresent) {
            applyEffect(player, effects.fullArmor1);
            applyEffect(player, effects.fullArmor2);
            player.setDynamicProperty("tcs_ohs_has_full_armor", true);
        } 
    }
}

async function handleHelmet(player) {
    const hadHelmet = player.getDynamicProperty("tcs_ohs_has_warriors_helmet");

    const helmetType = await getPlayerEquipmentType(player, "Head");
    const hasHelmet = helmetType === "tcs_ohs:warriors_helmet";
    const effectPresent = await hasEffect(player, effects.helmet);
    
    if (!hasHelmet) {
        if (hadHelmet && effectPresent)
            await removeEffect(player, effects.helmet);

        player.setDynamicProperty("tcs_ohs_has_warriors_helmet", false);
        return false;
    }

    player.setDynamicProperty("tcs_ohs_has_warriors_helmet", true);

    if (!effectPresent)
        await applyEffect(player, effects.helmet);

    return true;
}

async function handleChestplate(player) {
    const hadChestplate = player.getDynamicProperty("tcs_ohs_has_warriors_chestplate");

    const chestplateType = await getPlayerEquipmentType(player, "Chest");
    const hasChestplate = chestplateType === "tcs_ohs:warriors_chestplate";
    const effectPresent = await hasEffect(player, effects.chestplate);
    
    if (!hasChestplate) {
        if (hadChestplate && effectPresent)
            await removeEffect(player, effects.chestplate);

        player.setDynamicProperty("tcs_ohs_has_warriors_chestplate", false);
        return false;
    }

    player.setDynamicProperty("tcs_ohs_has_warriors_chestplate", true);

    if (!effectPresent)
        await applyEffect(player, effects.chestplate);

    return true;
}

async function handleLeggings(player) {
    const hadleggings = player.getDynamicProperty("tcs_ohs_has_warriors_leggings");

    const leggingsType = await getPlayerEquipmentType(player, "Legs");
    const hasLeggings = leggingsType === "tcs_ohs:warriors_leggings";
    const effectPresent = await hasEffect(player, effects.leggings);
    
    if (!hasLeggings) {
        if (hadleggings && effectPresent) 
            await removeEffect(player, effects.leggings);

        player.setDynamicProperty("tcs_ohs_has_warriors_leggings", false);
        return false;
    }

    player.setDynamicProperty("tcs_ohs_has_warriors_leggings", true);

    if (!effectPresent)
        await applyEffect(player, effects.leggings);

    return true;
}

async function handleBoots(player) {
    const hadBoots = player.getDynamicProperty("tcs_ohs_has_warriors_boots");

    const bootsType = await getPlayerEquipmentType(player, "Feet");
    const hasBoots = bootsType === "tcs_ohs:warriors_boots";
    const effectPresent = await hasEffect(player, effects.boots);
    
    if (!hasBoots) {
        if (hadBoots && effectPresent)
            await removeEffect(player, effects.boots);
        
        player.setDynamicProperty("tcs_ohs_has_warriors_boots", false);
        return false;
    }

    player.setDynamicProperty("tcs_ohs_has_warriors_boots", true);

    if (!effectPresent)
        await applyEffect(player, effects.boots);

    return true;
}

async function getPlayerEquipmentType(player, position) {
	let player_equipment = player.getComponent("equippable").getEquipment(position);
	if (player_equipment == undefined) 
		return undefined;

	return player_equipment.typeId;
}

export async function onEntityHurt(event) {
    const player = event.hurtEntity;

	const chestplateType = await getPlayerEquipmentType(player, "Chest");
    const hasChestplate = chestplateType === "tcs_ohs:warriors_chestplate";

    if (!hasChestplate)
        return;

    // Cancel previous interval
    const intervalNumber = player.getDynamicProperty("tcs_ohs_absorption_interval_number");
    if (intervalNumber)
        system.clearRun(intervalNumber);

    const newIntervalNumber = system.runTimeout(async () => {
        const chestplateType = await getPlayerEquipmentType(player, "Chest");
        const hasChestplate = chestplateType === "tcs_ohs:warriors_chestplate";
        if (!hasChestplate)
            return;

        resetEffect(player, effects.chestplate);
    }, 200); // 20s

    player.setDynamicProperty("tcs_ohs_absorption_interval_number", newIntervalNumber);
}

export async function resetEffect(player, effect) {
    const playerHasEffect = await hasEffect(player, effect);
    if (!playerHasEffect)
        return;

    await removeEffect(player, effect);
    await applyEffect(player, effect);
}

async function hasEffect(player, effect) {
    const playerEffect = player.getEffect(effect.type);
    if (playerEffect === undefined)
        return false;

    if (playerEffect.amplifier < effect.amplifier)
        return false;

    return true;
}

async function applyEffect(player, effect) {
    player.addEffect(effect.type, 9999999, { amplifier: effect.amplifier, showParticles: false })
}

async function removeEffect(player, effect) {
    player.removeEffect(effect.type);
}