import {
    ItemStack,
    world,
    system,
    EntityComponentTypes,
    EquipmentSlot
} from "@minecraft/server";
import {
    ActionFormData,
    ActionFormResponse,
    ModalFormData
} from "@minecraft/server-ui";

// Function to display the guide book GUI
function bookGui(player) {
    const gui = new ActionFormData()
        .title(`Ocean Expansion`);
    const text = [
        `§l§aOcean Expansion§r`,
        `§2Add-On By Hourglass Studios`,
        ``,
        `   The Ocean Expansion add-on for Minecraft enriches the underwater exploration experience with various tools, weapons, animals, and bosses. This add-on is designed to bring your adventure to the depths of the ocean with challenging and exciting features.`,
        ``,
        `§l§aList of Items§r`,
        ``,
        `§lScuba Helmet§r`,
        `[Diamond]  [Empty]  [Diamond]`,
        `[Diamond] [Diamond] [Diamond]`,  
        ` [Empty]   [Empty]   [Empty]`,
        ``,
        `§lScuba Chestplate§r`,
        `[Diamond] [Diamond] [Diamond]`,
        `[Diamond] [Diamond] [Diamond]`,  
        `[Diamond]  [Empty]  [Diamond]`,
        ``,
        `§lScuba Leggings§r`,
        `[Diamond]  [Empty]  [Diamond]`,
        `[Diamond]  [Empty]  [Diamond]`,  
        `[Diamond] [Diamond] [Diamond]`,
        ``,
        `§lScuba Boots§r`,
        `[Diamond]  [Empty]  [Diamond]`,
        ` [Empty]   [Empty]   [Empty]`,  
        `[Diamond]  [Empty]  [Diamond]`,
        ``,
        `§lDeep Sea Flares§r`,
        ``,
        `Illuminate the underwater, providing sufficient light for exploring in the darkness.`,
        ``,
        `   Recipe`,
        `\n\n\n\n\n\n\n\n`,
        ``,
        `§lDepthcharge§r`,
        ``,
        `Has two modes - normal and mine.`,
        ``,
        `Right-click to switch between normal mode (ignite with flint and steel) and mine mode (explodes when too close).`,
        ``,
        `   Recipe`,
        `\n\n\n\n\n\n\n\n`,
        ``,
        `§lHydro Pod§r`,
        ``,
        `Acts as an underwater base, providing a shelter and a place to store items, crouch and right click on the door to pick up a Hydro Pod, Place on a flat surface and dont try breaking it in or you cant pick it up again and would be unusable.`,
        ``,
        `   Recipe`,
        `\n\n\n\n\n\n\n\n`,
        ``,
        `§lSubmersible§r`,
        ``,
        `An underwater vehicle that helps explore the ocean, making it easier and safer for players to travel around, crouch and right click to pick up a Submersile.`,
        ``,
        `   Recipe`,
        `\n\n\n\n\n\n\n\n`,
        ``,
        `§lOxygen Canister§r`,
        ``,
        `A key material for crafting the Hydro Pod and Submersible, essential for long underwater adventures.`,
        ``,
        `   Recipe`,
        `\n\n\n\n\n\n\n\n`,
        ``,
        `§l§aList of Weapons§r`,
        ``,
        `§lNeptune's Wrath§r`,
        ``,
        `Traps nearby entities with waves until the target drowns, effective for combating underwater foes.`,
        ``,
        `   Recipe`,
        `\n\n\n\n\n\n\n\n`,
        ``,
        `§lHarpoon§r`,
        ``,
        `Very ideal for hunting and defending against ocean threats.`,
        ``,
        `   Recipe`,
        `\n\n\n\n\n\n\n\n`,
        ``,
        `§l§aWith 60+ Sea Creatures§r`,
        ``,
        ``,
        `§l§aBoss§r`,
        ``,
        `§lLeviathan Monarch§r`,
        ``,
        `Don't kill too many Sharks, or Leviathan Monarch will come for you.`
    ];
    const bodyText = text.join(`\n`);
    gui.body(bodyText);
    gui.button('Close');
    gui.show(player);
}

// Initialize the ItemStack for the guide book
const book = new ItemStack(`hourglass_uwx:guide_book`);

// Store the last use time of Neptune's Wrath
const lastNeptunesWrathUse = new Map();

// Cooldown time in seconds
const NEPTUNES_WRATH_COOLDOWN = 2;

// Event listener for item use
world.afterEvents.itemUse.subscribe((event) => {
    const player = event.source;
    const currentTime = new Date().getTime();
    
    if (!event.itemStack) return;

    // If the used item is the guide book, show the GUI
    if (event.itemStack.typeId === `hourglass_uwx:guide_book`) {
        bookGui(event.source);
    }

    // If the used item is Neptune's Wrath and the cooldown has passed
    if (event.itemStack.typeId === `hourglass_uwx:kontol`) {
        if (!lastNeptunesWrathUse.has(player)) {
            lastNeptunesWrathUse.set(player, currentTime);
            player.runCommand('execute as @e[c=1, rm=1, family=!unattackable,type=!item] at @s run summon hourglass_uwx:neptunes_wave ~~~');
            player.runCommand('playsound random.splash @s');
        } else {
            const lastUseTime = lastNeptunesWrathUse.get(player);
            const elapsedTime = (currentTime - lastUseTime) / 1000; // Time in seconds
            if (elapsedTime >= NEPTUNES_WRATH_COOLDOWN) {
                lastNeptunesWrathUse.set(player, currentTime);
                player.runCommand('execute as @e[c=1, rm=1, family=!unattackable,type=!item] at @s run summon hourglass_uwx:neptunes_wave ~~~');
                player.runCommand('playsound random.splash @s');
            } else {
                const remainingCooldown = Math.ceil(NEPTUNES_WRATH_COOLDOWN - elapsedTime);
                player.sendMessage(`§l§cNeptune's Wrath§r is still on cooldown. Please wait ${remainingCooldown} seconds.`);
            }
        }
    }
    if (event.itemStack.typeId === `minecraft:stick`) {
        checkArmorSet(event.source, 'hourglass_studios:scuba')
    }
});

// Event listener for entity deaths
world.afterEvents.entityDie.subscribe((event) => {
    const attacker = event.damageSource;
    const victim = event.deadEntity;
    if (victim.typeId === 'hourglass_uwx:shark') {
        victim.runCommand('scoreboard players add @p shark_killed 1');
        victim.runCommand('execute as @p[scores={shark_killed=31..}] at @s run summon hourglass_uwx:leviathan_monarch');
        victim.runCommand('execute as @p[scores={shark_killed=31..}] at @s run scoreboard players set @a shark_killed 0');
    };
});

// Event listener for player spawning
world.afterEvents.playerSpawn.subscribe((event) => {
    const { initialSpawn, player } = event;
    if (!initialSpawn) return;
    if (player.hasTag(`OceanExpansion`)) return;

    // Add tag and display message
    player.addTag(`OceanExpansion`);
    player.sendMessage(`§l§aOcean Expansion§r Add-On installed.`);

    // Add guide book to the player's inventory
    const inventory = player.getComponent('inventory');
    const container = inventory.container;
    container.addItem(book);

    // Create the scoreboard objective for tracking shark kills
    player.runCommand('scoreboard objectives add shark_killed dummy "Sharks Killed"');
});

// Event listener for arrow shooting to apply liquid inertia when using harpoon
world.afterEvents.projectileHitEntity.subscribe((event) => {
    const player = event.source;
    const projectile = event.projectile;
});
world.afterEvents.dataDrivenEntityTrigger.subscribe((e => {
    const t = e.entity;
    "save_hydro_pod" === e.eventId && t.dimension.getEntities({
        type: "hourglass_uwx:hydro_pod",
        closest: 1,
        location: t.location
    }).forEach((e => {
        e.dimension.getPlayers({
            closest: 1,
            location: e.location
        }).forEach((e => {
            hydroPodGUI2(e)
        }))
    }))
}))
system.runInterval(()=>{
    world.getPlayers().forEach(player=>{
        if(checkArmorSet(player, 'hourglass_studios:scuba')) {
            player.addEffect('night_vision', 20)
            player.addEffect('water_breathing', 20)
        }
    })
    world.getDimension("overworld").getEntities({
        type: "hourglass_uwx:hydro_pod",
        excludeTags: ["hourglass_uwx:added"]
    }).forEach((e => {
        e.addTag("hourglass_uwx:added"), e.dimension.getPlayers({
            closest: 1,
            location: e.location
        }).forEach((e => {
            hydroPodGUI(e)
        }))
    }))
})

function checkArmorSet(player, armor) {
    const comp = player.getComponent("equippable");
    let checkSet = {
        helmet: false,
        chestplate: false,
        leggings: false,
        boots: false
    }
    if (comp) {
        try {
            const slot = comp.getEquipmentSlot(EquipmentSlot.Head);
            //console.warn(`Your helmet is ${slot.typeId}`);
            if (slot.typeId === `${armor}_helmet`) {
                checkSet.helmet = true;
            }
        } catch (error) {
            // Error handling is silently ignored
        }
    
        try {
            const slot = comp.getEquipmentSlot(EquipmentSlot.Chest);
            //console.warn(`Your chestplate is ${slot.typeId}`);
            if (slot.typeId === `${armor}_chestplate`) {
                checkSet.chestplate = true;
            }
        } catch (error) {
            // Error handling is silently ignored
        }
    
        try {
            const slot = comp.getEquipmentSlot(EquipmentSlot.Legs);
            //console.warn(`Your leggings are ${slot.typeId}`);
            if (slot.typeId === `${armor}_leggings`) {
                checkSet.leggings = true;
            }
        } catch (error) {
            // Error handling is silently ignored
        }
    
        try {
            const slot = comp.getEquipmentSlot(EquipmentSlot.Feet);
            //console.warn(`Your boots are ${slot.typeId}`);
            if (slot.typeId === `${armor}_boots`) {
                checkSet.boots = true;
            }
        } catch (error) {
            // Error handling is silently ignored
        }
    }
    if (Object.values(checkSet).every(value => value === true)) {
        //console.warn(`ANJAY MATCHING!`);
        return true;
    }
}

function generateRandomHash() {
    return Math.floor(1e5 * Math.random()).toString().padStart(5, "0")
}

function hydroPodGUI(e) {
    if (e.getDynamicPropertyIds().filter((e => e.startsWith("hourglass_uwx:hydro_pod."))).length > 0) {
        const t = (new ActionFormData).title("HydroPod");
        t.body("Select Summon"), t.button("New Structure"), t.button("Load Structure"), t.show(e).then((t => {
            1 === t.selection && loadHydroPod(e)
        }))
    }
}

function hydroPodGUI2(e) {
    const t = (new ActionFormData).title("HydroPod");
    t.body("Remove Hydro Pod"), t.button("Save Structure"), t.button("Destroy Structure"), t.show(e).then((t => {
        0 === t.selection && saveHydroPod(e), 1 === t.selection && destroyHydroPod(e)
    }))
}

function saveHydroPod(e) {
    (new ModalFormData).title("Create new structure").textField("Enter Hydro Pod Name", "", "").show(e).then((t => {
        const o = t.formValues[0];
        o && (console.warn(`saved name: ${o}`), e.dimension.getEntities({
            type: "hourglass_uwx:hydro_pod",
            closest: 1,
            location: e.location
        }).forEach((t => {
            console.warn(`Struktur ${o} Tersimpan`);
            let r = null;
            t.hasTag("hourglass_uwx:dir.east") ? r = "dir.east" : t.hasTag("hourglass_uwx:dir.north") ? r = "dir.north" : t.hasTag("hourglass_uwx:dir.south") ? r = "dir.south" : t.hasTag("hourglass_uwx:dir.west") && (r = "dir.west"), console.warn(`direction is ${r}`);
            const s = o,
                n = generateRandomHash();
            t.runCommand(`structure save hourglass_uwx:hydro_pod.${n} ~-1~~-1 ~1~2~1 false disk`), t.runCommand("fill ~2~-1~2 ~-2~3~-2 air"), t.runCommand("kill @e[type=hourglass_uwx:hydro_pod_door, c=2, r=4]"), e.setDynamicProperty(`hourglass_uwx:hydro_pod.${n}/${r}`, s), t.remove()
        })))
    }))
}

function destroyHydroPod(e) {
    e.dimension.getEntities({
        type: "hourglass_uwx:hydro_pod",
        closest: 1,
        location: e.location
    }).forEach((e => {
        e.runCommand("fill ~2~~2 ~-2~3~-2 air replace hourglass_uwx:hydro_pod.block"), e.runCommand("fill ~2~~2 ~-2~3~-2 air destroy"), e.runCommand("kill @e[type=hourglass_uwx:hydro_pod_door, c=2, r=4]"), e.remove()
    }))
}

function loadHydroPod(e) {
    let t = [],
        o = [];
    const r = e.getDynamicPropertyIds().filter((e => e.startsWith("hourglass_uwx:hydro_pod.")));
    r.length > 0 && (r.forEach((r => {
        t.push(`${e.getDynamicProperty(r).split("/")[0]}`), o.push(r)
    })), console.warn(`Name: ${t.join(", ")}`), console.warn(`Hash: ${o.join(", ")}`), (new ModalFormData).title("Select Hydro Pod").dropdown("\n    §aSelect your hydro pod structure.§r\n    \n§l§e[§9Select Structure§e]", t, 0).show(e).then((r => {
        t[r.formValues[0]] && e.dimension.getEntities({
            type: "hourglass_uwx:hydro_pod",
            closest: 1,
            location: e.location
        }).forEach((s => {
            let n = null,
                a = null;
            {
                const e = o[r.formValues[0]];
                e.includes("east") && (s.hasTag("hourglass_uwx:dir.east") ? (n = "0_degrees", a = "east") : s.hasTag("hourglass_uwx:dir.north") ? (n = "270_degrees", a = "north") : s.hasTag("hourglass_uwx:dir.west") ? (n = "180_degrees", a = "west") : s.hasTag("hourglass_uwx:dir.south") && (n = "90_degrees", a = "south")), e.includes("north") && (s.hasTag("hourglass_uwx:dir.east") ? (n = "90_degrees", a = "east") : s.hasTag("hourglass_uwx:dir.north") ? (n = "0_degrees", a = "north") : s.hasTag("hourglass_uwx:dir.west") ? (n = "270_degrees", a = "west") : s.hasTag("hourglass_uwx:dir.south") && (n = "180_degrees", a = "south")), e.includes("west") && (s.hasTag("hourglass_uwx:dir.east") ? (n = "180_degrees", a = "east") : s.hasTag("hourglass_uwx:dir.north") ? (n = "90_degrees", a = "north") : s.hasTag("hourglass_uwx:dir.west") ? (n = "0_degrees", a = "west") : s.hasTag("hourglass_uwx:dir.south") && (n = "270_degrees", a = "south")), e.includes("south") && (s.hasTag("hourglass_uwx:dir.east") ? (n = "270_degrees", a = "east") : s.hasTag("hourglass_uwx:dir.north") ? (n = "180_degrees", a = "north") : s.hasTag("hourglass_uwx:dir.west") ? (n = "90_degrees", a = "west") : s.hasTag("hourglass_uwx:dir.south") && (n = "0_degrees", a = "south"))
            }
            let l = null;
            e.getDynamicPropertyIds().forEach((e => {
                e === o[r.formValues[0]] && (l = o[r.formValues[0]].split("/")[0])
            })), s.runCommand(`structure load "${l}" ~-1~~-1 ${n}`), console.warn(`direction ${a}, rotation ${n}`), e.setDynamicProperty(o[r.formValues[0]], void 0), console.warn(`NAME:${t[r.formValues[0]]},HASH:${o[r.formValues[0]]}`)
        }))
    })))
}
