import { system, BlockPermutation } from '@minecraft/server';
import * as game from "./game";
import * as vector3 from "./vector3";
import * as chest_reward from "./chest_reward";
const airBlock = BlockPermutation.resolve("air");

const data = [
	// Generic
	{ 
        id: "zombie_outpost", range: 34,
        kill: [ { id: "minecraft:zombie", name: "Zombies", count: 7 } ]
    },
    { 
        id: "mushroom_temple", range: 37 ,
        collect: [ { id: "minecraft:red_mushroom", name: "Red Mushrooms", count: 16 } ]
    },
	{ 
        id: "skeleton_dungeon", range: 42,
        kill: [ { id: "minecraft:skeleton", name: "Skeletons", count: 7 } ]
    },
	{ 
        id: "creeper_statue", range: 37,
        kill: [ { id: "minecraft:creeper", name: "Creepers", count: 7 } ]
    },
    { 
        id: "badlands_temple", range: 37 ,
        collect: [ { id: "minecraft:raw_gold", name: "Raw Gold", count: 15 } ],
        clean: [ { id: "minecraft:skeleton" } ]
    },
    { 
        id: "campsite", range: 30 ,
        collect: [ { id: "minecraft:cooked_porkchop", name: "Cooked Porkchops", count: 10 } ],
        clean: [ { id: "minecraft:pig" } ]
    },
    { 
        id: "phoenix_monument", range: 38 ,
        kill: [ { id: "minecraft:blaze", name: "Blazes", count: 5 } ]
    },
	{ 
        id: "lighthouse", range: 34,
        kill: [ { id: "tcs_ohs:drowned", name: "Drowned", count: 10 } ]
    },
	{ 
        id: "desert_ruins", range: 44,
        break: [ { id: "minecraft:mob_spawner", name: "Husk Monster Spawners", count: 6 } ]
    },
	{ 
        id: "dark_tower", range: 35,
        kill: [ { id: "minecraft:evocation_illager", name: "Evokers", count: 2 }, { id: "minecraft:pillager", name: "Pillagers", count: 5 } ]
    },
	{ 
        id: "pirate_ship", range: 44,
        kill: [ { id: "minecraft:pillager", name: "Pillagers", count: 5 } ]
    },
    { 
        id: "mighty_prison_tower", range: 35 ,
        kill: [ { id: "minecraft:skeleton", name: "Skeletons", count: 6 } ],
        clean: [{ id: "minecraft:silverfish" } ]
    },
	{ 
        id: "ice_castle", range: 41,
        kill: [ { id: "minecraft:stray", name: "Strays", count: 6 } ]
    },
	{ 
        id: "obelisk", range: 35,
        kill: [ { id: "minecraft:wither_skeleton", name: "Wither Skeleton", count: 5 } ]
    },
	{ 
        id: "end_castle", range: 40,
        kill: [ { id: "minecraft:enderman", name: "Endermen", count: 8 } ]
    },
    { 
        id: "end_tower", range: 34 ,
        collect: [ { id: "minecraft:shulker_shell", name: "Shulker Shells", count: 6 } ],
        clean: [ { id: "minecraft:shulker" } ]
    },
    { 
        id: "medieval_tower", range: 34 ,
        collect: [ { id: "minecraft:iron_sword", name: "Iron Swords", count: 3 } ],
        clean: [ { id: "minecraft:pillager" } ]
    },
	{ 
        id: "sunken_temple", range: 37,
        break: [ { id: "minecraft:mob_spawner", name: "Drowned Monster Spawners", count: 3 } ]
    },
	{ 
        id: "ancient_temple_2", range: 44,
        break: [ { id: "minecraft:mob_spawner", name: "Bogged Monster Spawners", count: 3 } ]
    },
    { 
        id: "space_rocket", range: 36 ,
        collect: [ { id: "minecraft:iron_block", name: "Iron Blocks", count: 4 } ]
    },
	{ 
        id: "ufo", range: 39,
        kill: [ { id: "minecraft:endermite", name: "Endermites", count: 8 } ]
    },
	{ 
        id: "desert_pyramid", range: 44,
        kill: [ { id: "minecraft:husk", name: "Husks", count: 8 } ]
    },
    { 
        id: "enderman_statue", range: 35 ,
        collect: [ { id: "minecraft:ender_pearl", name: "Ender Pearls", count: 3 } ]
    },
	{ 
        id: "frozen_shipwreck", range: 31,
        kill: [ { id: "minecraft:stray", name: "Stray", count: 4 } ]
    },
    { 
        id: "village_castle", range: 44 ,
        collect: [ { id: "minecraft:emerald", name: "Emeralds", count: 10 } ]
    },
    { 
        id: "giant_tree_house", range: 44 ,
        collect: [ { id: "minecraft:apple", name: "Apples", count: 6 } ]
    },
    { 
        id: "ancient_tower", range: 29 ,
        collect: [ { id: "minecraft:beacon", name: "Beacon", count: 1 } ]
    },
    { 
        id: "amethyst_tower", range: 31 ,
        collect: [ { id: "minecraft:end_crystal", name: "End Crystal", count: 1 } ]
    },
    { 
        id: "huge_nether_portal", range: 31 ,
        collect: [ { id: "minecraft:obsidian", name: "Obsidian", count: 5 } ]
    },
    { 
        id: "wizard_tower", range: 34 ,
        collect: [ { id: "minecraft:enchanted_book", name: "Enchanted Books", count: 3 } ],
        clean: [ { id: "minecraft:witch" } ]
    },
    { 
        id: "animal_farm", range: 28 ,
        collect: [ { id: "minecraft:wool", name: "Wool", count: 3 }, { id: "minecraft:milk_bucket", name: "Milk Buckets", count: 3 }  ]
    }
]

export function getData(id) {
    if (id === undefined)
        return undefined;
    let questIndex = data.findIndex((element) => element.id === id);
    if (questIndex === -1)
        return undefined;
    return data[questIndex];
}

export async function onTick() {
    // Get all quest givers
    let questGivers = await game.getEntities("tcs_ohs:quest_giver");
    
    // Handle first-time quest dialogue display
    for (let questGiver of questGivers) {
        //if (questGiver.nameTag !== "Quest Guide")
        //    questGiver.nameTag = "Quest Guide";
        if (questGiver.getDynamicProperty("tcs_ohs_quest_state") !== undefined) 
            continue;

        let questId = questGiver.getDynamicProperty("tcs_ohs_quest_id");
        if (questId === undefined) 
            continue;
        // Check for nearby players
        let players = await game.getEntitiesInRange("minecraft:player", questGiver.dimension, questGiver.location, 0, 3);
        if (players !== undefined && players.length > 0) 
        {
            await game.runPlayerCommand(players[0], `dialogue open @e[type=tcs_ohs:quest_giver,r=4] @s ${questId}_active`);
            questGiver.setDynamicProperty("tcs_ohs_quest_state", "quest_active_first_time");
        }
            
    }
}

function getQuestSubtitle(questData)
{
    let subtitle = "§6";
    if (questData.kill !== undefined) {
        subtitle += "Kill: ";
        for (let req of questData.kill) {
            subtitle += `${req.count} ${req.name}, `;
        }
    }
    if (questData.break !== undefined) {
        subtitle += "Destroy: ";
        for (let req of questData.break) {
            subtitle += `${req.count} ${req.name}, `;
        }
    }
    if (questData.collect !== undefined) {
        subtitle += "Collect: ";
        for (let req of questData.collect) {
            subtitle += `${req.count} ${req.name}, `;
        }
    }
    return subtitle.slice(0, -2); // Remove the last comma and space
}

export async function announceQuestProgress(questGiver, questData, message) {
    let corner1 = vector3.copy(questGiver.location).subtract(questData.range);
    let corner2 = vector3.copy(questGiver.location).add(questData.range);
    let players = await game.getPlayersInArea(questGiver.dimension, corner1, corner2, "xz");
    if (players === undefined || players.length == 0)
        return;

    for (let player of players) 
    {
        player.onScreenDisplay.setActionBar(message);
        game.playSound(player, "@s", "tcs_ohs:info");
    }
}
export async function announceQuestComplete(questGiver, questData) {
    let corner1 = vector3.copy(questGiver.location).subtract(questData.range);
    let corner2 = vector3.copy(questGiver.location).add(questData.range);
    let players = await game.getPlayersInArea(questGiver.dimension, corner1, corner2, "xz");
    if (players === undefined || players.length == 0)
        return;

    for (let player of players) {
        await player.onScreenDisplay.updateSubtitle("§6Return to the Quest Guide!");
        await player.onScreenDisplay.setTitle(" ");
    }
}

export async function cleanMobs(questGiver, questData) {
    let corner1 = vector3.copy(questGiver.location).subtract(questData.range+20);
    let corner2 = vector3.copy(questGiver.location).add(questData.range+20);

    // Remove all mob spawners in range
    let mobSpawners = await game.getEntitiesInArea("tcs_ohs:mob_spawner", questGiver.dimension, corner1, corner2, "xz");
    if (mobSpawners !== undefined) {
        for (let mobSpawner of mobSpawners) {
            mobSpawner.remove();
        }
    }

    // Remove all remaining target mobs in range
    if (questData.kill !== undefined)
    {
        for (let req of questData.kill) {
            let targetMobs = await game.getEntitiesInArea(req.id, questGiver.dimension, corner1, corner2, "xz");
            if (targetMobs !== undefined) {
                for (let mob of targetMobs) {
                    try{
                        mob.remove();
                    }
                    catch (e) { }
                }
            }
        }
    }
    if (questData.clean !== undefined) {
        for (let req of questData.clean) {
            let targetMobs = await game.getEntitiesInArea(req.id, questGiver.dimension, corner1, corner2, "xz");
            if (targetMobs !== undefined) {
                for (let mob of targetMobs) {
                    try{
                        mob.remove();
                    }
                    catch (e) { }
                }
            }
        }
    }
}

export async function onEntityDie(event) {
    let killedEntityType = event.deadEntity.typeId;
    
    let questGivers = await game.getEntities("tcs_ohs:quest_giver");
    for (let questGiver of questGivers) {
        let questId = questGiver.getDynamicProperty("tcs_ohs_quest_id");
        let questData = getData(questId);
        if (questData === undefined)
            continue;
        if (questData.kill === undefined)
            continue;

        // Find the matching kill requirement
        let killRequirement = questData.kill.find(req => req.id === killedEntityType);
        if (killRequirement === undefined)
            continue;

        let questState = questGiver.getDynamicProperty("tcs_ohs_quest_state");
        if (questState !== "quest_active")
            continue;

        // Check if quest giver is in range of the event location
        if (!vector3.areLocationsInRangeXZ(questGiver.location, event.deadEntity.location, questData.range))
            continue;

        // Get progress for this specific entity type
        let progressKey = `tcs_ohs_quest_progress_${killedEntityType}`;
        let progress = questGiver.getDynamicProperty(progressKey) || 0;
        progress++;
        questGiver.setDynamicProperty(progressKey, progress);
        if (progress <= killRequirement.count) 
            announceQuestProgress(questGiver, questData, `${progress}/${killRequirement.count} ${killRequirement.name} Killed`);

        // Check if quest is complete for this entity type
        if (progress < killRequirement.count)
            continue;
        
        // Check if all other entity types are also complete
        let allComplete = true;
        for (let req of questData.kill) {
            let entityProgress = questGiver.getDynamicProperty(`tcs_ohs_quest_progress_${req.id}`) || 0;
            if (entityProgress < req.count) {
                allComplete = false;
                break;
            }
        }

        if (allComplete) {
            questGiver.setDynamicProperty("tcs_ohs_quest_state", "quest_finished_first_time");
            questGiver.triggerEvent("tcs_ohs:quest_goal_reached");
            await announceQuestComplete(questGiver, questData);
            await cleanMobs(questGiver, questData);
        }
    }
}

export async function onPlayerBreakBlock(event) {
    let brokenBlockType = event.brokenBlockPermutation.type.id;
    let questGivers = await game.getEntities("tcs_ohs:quest_giver");
    for (let questGiver of questGivers) {
        let questId = questGiver.getDynamicProperty("tcs_ohs_quest_id");
        let questData = getData(questId);
        if (questData === undefined || questData.break === undefined)
            continue;
        // Find the matching break requirement
        let breakRequirement = questData.break.find(req => req.id === brokenBlockType);
        if (breakRequirement === undefined)
            continue;

        let questState = questGiver.getDynamicProperty("tcs_ohs_quest_state");
        let notiftProgress = (questState === "quest_active");
        //if (questState !== "quest_active")
        //    continue;

        // Check if quest giver is in range of the event location
        if (!vector3.areLocationsInRangeXZ(questGiver.location, event.player.location, questData.range))
            continue;

        let corner1 = vector3.copy(questGiver.location).subtract(questData.range);
        let corner2 = vector3.copy(questGiver.location).add(questData.range);
        let players = await game.getPlayersInArea(questGiver.dimension, corner1, corner2, "xz");
        if (players === undefined || players.length == 0)
            continue;


        // Get progress for this specific block type
        let progressKey = `tcs_ohs_quest_progress_${brokenBlockType}`;
        let progress = questGiver.getDynamicProperty(progressKey) || 0;
        if (progress < breakRequirement.count)
            progress++;
        questGiver.setDynamicProperty(progressKey, progress);
        
        if (notiftProgress && progress <= breakRequirement.count) 
            announceQuestProgress(questGiver, questData, `${progress}/${breakRequirement.count} ${breakRequirement.name} Destroyed`);

        // Check if quest is complete for this block type
        if (!notiftProgress || progress < breakRequirement.count) 
            continue;

        // Check if all other block types are also complete
        let allComplete = true;
        for (let req of questData.break) {
            let blockProgress = questGiver.getDynamicProperty(`tcs_ohs_quest_progress_${req.id}`) || 0;
            if (blockProgress < req.count) {
                allComplete = false;
                break;
            }
        }

        if (allComplete) {
            questGiver.setDynamicProperty("tcs_ohs_quest_state", "quest_finished_first_time");
            questGiver.triggerEvent("tcs_ohs:quest_goal_reached");
            await announceQuestComplete(questGiver, questData);
        }
    }
}

export async function onPlayerInteractWithEntity(event) {
    let questState = event.target.getDynamicProperty("tcs_ohs_quest_state");
    
    let questId = event.target.getDynamicProperty("tcs_ohs_quest_id");
    let questData = getData(questId);
    if (questData === undefined)
        return;
    
    if (questState === undefined || questState === "quest_active_first_time") {
        await game.runPlayerCommand(event.player, `dialogue open @e[type=tcs_ohs:quest_giver,r=10,c=1] @s ${questId}_active`);
    }
    else if (questState === "quest_active") {
        // Quest is in progress
        if (await checkPlayerCollectedItems(event.player, questData)) {
            event.target.setDynamicProperty("tcs_ohs_quest_state", "quest_finished_first_time");
            if (questData.clean !== undefined) 
                await cleanMobs(event.target, questData);
            //announceQuestComplete(event.target, questData);
            await game.runPlayerCommand(event.player, `dialogue open @e[type=tcs_ohs:quest_giver,r=10,c=1] @s ${questId}_finished`);
        } else {
            await game.runPlayerCommand(event.player, `dialogue open @e[type=tcs_ohs:quest_giver,r=10,c=1] @s ${questId}_active`);
        }
    }
    else if (questState === "quest_finished" || questState === "quest_finished_first_time") {
        await game.runPlayerCommand(event.player, `dialogue open @e[type=tcs_ohs:quest_giver,r=10,c=1] @s ${questId}_finished`);
    }
}

export async function checkPlayerCollectedItems(player, questData) {
    if (questData.collect === undefined)
        return false;

    const inventory = player.getComponent("minecraft:inventory").container;
    for (let req of questData.collect) {
        let totalAmount = 0;

        // Check main inventory
        for (let i = 0; i < inventory.size; i++) {
            let item = inventory.getItem(i);
            if (item !== undefined && item.typeId === req.id)
                totalAmount += item.amount;
            else if (item !== undefined && req.id === "minecraft:wool" && item.typeId.endsWith("wool"))
                totalAmount += item.amount;
        }

        if (totalAmount < req.count)
            return false;
    }

    return true;
}

export async function clearPlayerWool(player, woolAmount) {
    const inventory = player.getComponent("minecraft:inventory").container;
    let leftToClear = woolAmount;

    for (let i = 0; i < inventory.size; i++) {
        let item = inventory.getItem(i);
        if (item !== undefined && item.typeId.endsWith("wool")) {
            let clearAmount = Math.min(item.amount, leftToClear);
            leftToClear -= clearAmount;
            await game.runPlayerCommand(player, `clear @s ${item.typeId} -1 ${clearAmount}`);
            if (leftToClear <= 0)
                break;
        }
    }
}

export async function onScriptEventReceive(event) {
    
    let questGiver = event.sourceEntity;
    if (event.id === "tcs_ohs:quest_load") {
        // Handle quest loading
		let commandBlockLocation = vector3.Down.add(event.sourceEntity.location);
		questGiver.dimension.setBlockPermutation(event.sourceEntity.location, airBlock);
		questGiver.dimension.setBlockPermutation(commandBlockLocation, airBlock);
        //questGiver.nameTag = "Quest Guide";

        let questId = event.message;
        let questData = getData(questId);

        if (questData !== undefined) {
            questGiver.setDynamicProperty("tcs_ohs_quest_id", questId);

            // Trigger appropriate event based on quest type
            if (questData.kill !== undefined) {
                questGiver.triggerEvent("tcs_ohs:fight_quest");
            }
            if (questData.break !== undefined) {
                questGiver.triggerEvent("tcs_ohs:block_quest");
            }
            if (questData.collect !== undefined) {
                questGiver.triggerEvent("tcs_ohs:collect_quest");
            }
        }
    }
    
    else if (event.id === "tcs_ohs:quest_active") {
        if (event.message === "open") {
            let currentState = questGiver.getDynamicProperty("tcs_ohs_quest_state");
            if (currentState === undefined) {
                questGiver.setDynamicProperty("tcs_ohs_quest_state", "quest_active_first_time");
            }
        }
        else if (event.message === "close") {
            let currentState = questGiver.getDynamicProperty("tcs_ohs_quest_state");
            if (currentState === "quest_active_first_time") {
                // Get players in range and show title
                let players = await game.getEntitiesInRange("minecraft:player", questGiver.dimension, questGiver.location, 0, 10);
                if (players !== undefined) {
                    for (let player of players) {
                        let subtitle = getQuestSubtitle(getData(questGiver.getDynamicProperty("tcs_ohs_quest_id")));
                        //await player.onScreenDisplay.setActionBar(subtitle);
                        await player.onScreenDisplay.updateSubtitle(subtitle);
                        await player.onScreenDisplay.setTitle("§2QUEST STARTED!");
                        await game.playSound(player, "@s", "tcs_ohs:quest_started");
                    }
                }
                questGiver.setDynamicProperty("tcs_ohs_quest_state", "quest_active");
            }
            //questGiver.nameTag = "Quest Guide";
        }
    }
    else if (event.id === "tcs_ohs:quest_finished") {
        if (event.message === "open") {
            let currentState = questGiver.getDynamicProperty("tcs_ohs_quest_state");
            if (currentState === "quest_active") {
                questGiver.setDynamicProperty("tcs_ohs_quest_state", "quest_finished_first_time");
            }
        }
        else if (event.message === "close") {
            let currentState = questGiver.getDynamicProperty("tcs_ohs_quest_state");
            if (currentState === "quest_finished_first_time") {
                // Get players in range and show title
                let players = await game.getEntitiesInRange("minecraft:player", questGiver.dimension, questGiver.location, 0, 10);
                if (players !== undefined) {
                    for (let player of players) {
                        player.onScreenDisplay.setTitle("§2QUEST COMPLETED!");
                        game.playSound(player, "@s", "tcs_ohs:quest_finished");
                        player.dimension.spawnParticle("tcs_ohs:quest_floor", player.location);
                        player.dimension.spawnParticle("tcs_ohs:quest_fireworks", player.location);

                        // Clear collected items if this was a collect quest
                        let questId = questGiver.getDynamicProperty("tcs_ohs_quest_id");
                        let questData = getData(questId);
                        if (questData !== undefined && questData.collect !== undefined) {
                            for (let req of questData.collect) {
                                if (req.id === "minecraft:wool") 
                                    await clearPlayerWool(player, req.count);
                                else
                                    await game.runPlayerCommand(player, `clear @s ${req.id} -1 ${req.count}`);
                            }
                        }
                    }
                }

                // Find and show treasure chests in 10-block radius
                let chests = await game.getEntitiesInRange("tcs_ohs:reward_chest", questGiver.dimension, questGiver.location, 0, 10);
                if (chests !== undefined) {
                    for (let chest of chests) {
                        chest.triggerEvent("tcs_ohs:show");
                        await chest_reward.createTreasure(chest);
                        chest.nameTag = "Treasure chest";
                    }
                }

                questGiver.setDynamicProperty("tcs_ohs_quest_state", "quest_finished");
                questGiver.triggerEvent("tcs_ohs:quest_finished");
            }
        }
    }
} 