import { ItemStack, system } from "@minecraft/server";

export class EntityBreederComponent {
    constructor() {
        this.onStepOn = this.onStepOn.bind(this);
        this.onPlayerInteract = this.onPlayerInteract.bind(this);
        this.BREEDABLE_ENTITY_LIST = [
            "minecraft:cow",
            "minecraft:pig",
            "minecraft:sheep",
            "minecraft:chicken",
            //  "minecraft:rabbit",
        ];

        this.BREED_ITEMS = {
            cow: ["minecraft:wheat"],
            //    rabbit: ["minecraft:carrots", "minecraft:golden_carrots", "minecraft:dandelion"],
            pig: ["minecraft:carrot", "minecraft:beetroot", "minecraft:potato"],
            sheep: ["minecraft:wheat"],
            chicken: ["minecraft:wheat_seeds", "minecraft:beetroot_seeds", "minecraft:melon_seeds", "minecraft:pumpkin_seeds", "minecraft:pitcher_pod", "minecraft:torchflower_seeds"]
        };
    }

    onPlayerInteract(e) {
        const { block, player } = e;
        const selectedSlot = player.selectedSlotIndex;
        const handItem = player.getComponent("inventory").container.getItem(selectedSlot);

        if (handItem?.typeId === "pb_red:redstone_wrench") {
            this.rotateBlockState(block, [
                { state: "minecraft:cardinal_direction", values: ["north", "east", "south", "west"] },
                { state: "minecraft:facing_direction", values: ["north", "east", "south", "west", "up", "down"] }
            ]);
        }
    }

    rotateBlockState(block, stateConfigs) {
        for (const { state, values } of stateConfigs) {
            const currentState = block.permutation.getState(state);
            if (currentState !== undefined) {
                const nextState = this.getNextState(currentState, values);
                block.setPermutation(block.permutation.withState(state, nextState));
                block.dimension.runCommand(`playsound vr.stutterturn @a ${block.location.x} ${block.location.y} ${block.location.z}`);
                return;
            }
        }
    }

    getNextState(currentState, stateValues) {
        const currentIndex = stateValues.indexOf(currentState);
        return stateValues[(currentIndex + 1) % stateValues.length];
    }

    onStepOn(e) {
        const { block } = e;
        const direction = block.permutation.getState("minecraft:cardinal_direction");
        const offsets = this.getDirectionalOffsets(direction);

        for (const entity of block.dimension.getEntitiesAtBlockLocation(block.location)) {
            if (entity.typeId === "minecraft:player") return;

            this.centerEntityOnBlock(entity, block.location, offsets.frontOffset);
            const impulseVector = this.getImpulseVector(offsets.frontOffset);
            this.applyImpulseToEntity(entity, impulseVector);

            if (this.BREEDABLE_ENTITY_LIST.includes(entity.typeId)) {
                this.handleBreeding(entity, block, offsets.leftOffset);
            }
        }
    }

    centerEntityOnBlock(entity, blockLocation, frontOffset) {
        const centerX = blockLocation.x + 0.5;
        const centerZ = blockLocation.z + 0.5;
        const { x, z } = entity.location;

        if (Math.abs(frontOffset.x) > Math.abs(frontOffset.z)) {
            if (z !== centerZ) entity.teleport({ x, y: entity.location.y + 0.05, z: centerZ });
        } else {
            if (x !== centerX) entity.teleport({ x: centerX, y: entity.location.y + 0.05, z });
        }
        entity.clearVelocity();
    }

    getImpulseVector(frontOffset) {
        return { x: frontOffset.x / 3, y: 0.05, z: frontOffset.z / 3 };
    }

    applyImpulseToEntity(entity, impulseVector) {
        entity.applyImpulse(impulseVector);
    }

    handleBreeding(entity, block, leftOffset) {
        const breedCooldown = this.getEntityBreedCooldown(entity);

        if (this.canBreed(entity, block, leftOffset, breedCooldown)) {
            const breedState = this.getBreedStateForEntity(entity.typeId);

            if (block.permutation.getState(breedState)) {
                this.breedEntity(entity, block, leftOffset);
            } else {
                block.setPermutation(block.permutation.withState(breedState, true));
                entity.remove();
            }
        }
    }

    getEntityBreedCooldown(entity) {
        const cooldownTag = entity.getTags().find(tag => tag.startsWith("breed_cooldown:"));
        const cooldownTime = cooldownTag ? parseInt(cooldownTag.split(":")[1]) : 0;
        //     console.warn(Date.now() - cooldownTime)
        return Date.now() - cooldownTime > (3 * 60 * 1000); // 3 minutes

    }

    canBreed(entity, block, leftOffset, breedCooldown) {
        const breedItems = this.getBreedItemsForEntity(entity.typeId);
        return breedCooldown &&
            this.isEntityAdult(entity) &&
            this.hasBreedItemsInChest(block, leftOffset, breedItems);
    }

    isEntityAdult(entity) {
        return !entity.getComponent("minecraft:is_baby");
    }

    hasBreedItemsInChest(block, leftOffset, breedItems) {
        const chestBlock = block.offset(leftOffset);

        if (!this.isValidContainer(chestBlock)) return false;

        const inventory = chestBlock.getComponent("minecraft:inventory")?.container;
        if (!inventory) return false;

        // Aggregate the total count of breed items
        let totalAmount = 0;

        for (let slot = 0; slot < inventory.size; slot++) {
            const item = inventory.getItem(slot);

            if (item && breedItems.includes(item.typeId)) {
                totalAmount += item.amount;
                if (totalAmount >= 10) return true;
            }
        }

        return false;
    }


    breedEntity(entity, block, leftOffset) {
        const offsets = this.getDirectionalOffsets(block.permutation.getState("minecraft:cardinal_direction"));

        const cooldownTag = entity.getTags().find(tag => tag.startsWith("breed_cooldown:"));
        if (cooldownTag) entity.removeTag(cooldownTag)
        entity.addTag(`breed_cooldown:${Date.now()}`);
        this.resetBreedStates(block);

        const spawnLocations = {
            adult: this.getSpawnLocation(block, offsets.frontOffset),
            baby: this.getSpawnLocation(block, offsets.rightOffset),
        };

        this.spawnEntities(entity.typeId, spawnLocations, entity);
        this.consumeBreedItems(block, leftOffset, entity.typeId);
        this.spawnBreedingEffects(block);
    }

    resetBreedStates(block) {
        for (const entityType of this.BREEDABLE_ENTITY_LIST) {
            const breedState = this.getBreedStateForEntity(entityType);
            block.setPermutation(block.permutation.withState(breedState, false));
        }
    }

    getSpawnLocation(block, offset) {
        return {
            x: block.location.x + offset.x + 0.5,
            y: block.location.y + 0.05,
            z: block.location.z + offset.z + 0.5,
        };
    }

    spawnEntities(entityType, locations, entity) {

        entity.runCommand(`summon ${entityType} ${locations.baby.x} ${locations.baby.y} ${locations.baby.z} 0 0 minecraft:entity_born`)
        const babyEntity = entity.dimension.getEntities({ location: locations.baby, maxDistance: 1 }).filter(entity => !entity.hasTag("pb_red:breeder_summoned"))[0]
        if (!babyEntity) return
        babyEntity.addTag("pb_red:breeder_summoned")
        system.runTimeout(() => {
            try {
                babyEntity.removeTag("pb_red:breeder_summoned")
            } catch { }
        }, 10)

        entity.runCommand(`summon ${entityType} ${locations.adult.x} ${locations.adult.y} ${locations.adult.z} 0 0 minecraft:spawn_adult`)
        const adultEntity = entity.dimension.getEntities({ location: locations.adult, maxDistance: 1 }).filter(entity => !entity.hasTag("pb_red:breeder_summoned"))[0]
        if (!adultEntity) return
        adultEntity.addTag(`breed_cooldown:${Date.now()}`)
        adultEntity.addTag("pb_red:breeder_summoned")
        system.runTimeout(() => {
            try {
                adultEntity.removeTag("pb_red:breeder_summoned")
            } catch { }
        }, 10)

    }

    consumeBreedItems(block, leftOffset, entityType) {
        const chestBlock = block.offset(leftOffset);
        const inventory = chestBlock.getComponent("minecraft:inventory")?.container;
        const breedItems = this.getBreedItemsForEntity(entityType);

        const chestResources = [];
        for (let slot = 0; slot < inventory.size; slot++) {
            const item = inventory.getItem(slot);
            if (item) chestResources.push({ id: item.typeId, amount: item.amount, slot });
        }

        // Aggregate the total count of breed items
        let totalAmount = 0;
        const slotsToUpdate = [];

        for (const chestItem of chestResources) {
            if (breedItems.includes(chestItem.id)) {
                slotsToUpdate.push(chestItem);
                totalAmount += chestItem.amount;

                if (totalAmount >= 10) break;
            }
        }

        // If sufficient items exist, consume them
        if (totalAmount >= 10) {
            let remainingToRemove = 10;

            for (const chestItem of slotsToUpdate) {
                const amountToRemove = Math.min(chestItem.amount, remainingToRemove);
                remainingToRemove -= amountToRemove;

                let newAmount = chestItem.amount - amountToRemove
                inventory.setItem(
                    chestItem.slot,
                    newAmount > 0 ? new ItemStack(chestItem.id, newAmount) : null
                );

                if (remainingToRemove === 0) break;
            }
        }
    }


    spawnBreedingEffects(block) {
        for (let i = 0; i < 10; i++) {
            const offset = this.getRandomOffset();
            const particleLocation = {
                x: block.location.x + offset.x,
                y: block.location.y + 2 + offset.y,
                z: block.location.z + offset.z,
            };
            block.dimension.spawnParticle("minecraft:heart_particle", particleLocation);
        }
        block.dimension.runCommand(`playsound random.levelup @a ${block.location.x} ${block.location.y} ${block.location.z} 0.5`);
    }

    getRandomOffset() {
        const range = 1.0;
        return {
            x: (Math.random() - 0.5) * 2 * range,
            y: Math.random() * range,
            z: (Math.random() - 0.5) * 2 * range,
        };
    }

    getBreedStateForEntity(entityType) {
        const entityName = entityType.split(":")[1];
        return `pb_red:waiting_for_${entityName}`;
    }

    getBreedItemsForEntity(entityType) {
        const entityName = entityType.split(":")[1];
        return this.BREED_ITEMS[entityName] || [];
    }

    getDirectionalOffsets(direction) {
        const directions = {
            "north": { frontOffset: { x: 0, y: 0, z: -1 }, rightOffset: { x: 1, y: 0, z: 0 }, leftOffset: { x: -1, y: 0, z: 0 } },
            "south": { frontOffset: { x: 0, y: 0, z: 1 }, rightOffset: { x: -1, y: 0, z: 0 }, leftOffset: { x: 1, y: 0, z: 0 } },
            "east": { frontOffset: { x: 1, y: 0, z: 0 }, rightOffset: { x: 0, y: 0, z: 1 }, leftOffset: { x: 0, y: 0, z: -1 } },
            "west": { frontOffset: { x: -1, y: 0, z: 0 }, rightOffset: { x: 0, y: 0, z: -1 }, leftOffset: { x: 0, y: 0, z: 1 } },
        };
        return directions[direction] || {};
    }

    isValidContainer(block) {
        if (!block) return;
        const validContainers = [
            "minecraft:chest",
            "minecraft:hopper",
            "minecraft:barrel",
            "minecraft:dropper",
            "minecraft:dispenser",
            "minecraft:trapped_chest",
            //shulker box
            "minecraft:undyed_shulker_box",
            "minecraft:black_shulker_box",
            "minecraft:blue_shulker_box",
            "minecraft:brown_shulker_box",
            "minecraft:cyan_shulker_box",
            "minecraft:gray_shulker_box",
            "minecraft:green_shulker_box",
            "minecraft:light_blue_shulker_box",
            "minecraft:light_gray_shulker_box",
            "minecraft:lime_shulker_box",
            "minecraft:magenta_shulker_box",
            "minecraft:orange_shulker_box",
            "minecraft:pink_shulker_box",
            "minecraft:purple_shulker_box",
            "minecraft:red_shulker_box",
            "minecraft:white_shulker_box",
            "minecraft:yellow_shulker_box",


        ];
        return validContainers.includes(block.typeId);
    }
}
