import { world, system, Block, ItemStack, Entity } from "@minecraft/server";
import { Vec3 } from "../Vec3";
import * as connectable from "./connectable";
import * as GlobarVars from "../GlobalVars";
/**
 * 
 * @param {Block} block 
 */
export function onTick(block) {
    const state = block?.permutation.getState('cy_cr:on') || false;
    const onByOther = block?.permutation.getState('cy_cr:on_by_other') || false;
    const cardinal = block?.permutation.getState('minecraft:cardinal_direction');
    const spawnItemCooldown = block?.permutation.getState(`cy_cr:spawn_item_cooldown`) ?? 0;
    const fullMessageCooldown = block.permutation.getState(`cy_cr:full_message_cooldown`) ?? 0;

    if (cardinal) {
        getBlock();

        async function getBlock() {
            const blockFound = await GlobarVars.GetRedstoneInRadius(
                { x: block?.location.x, y: block?.location.y, z: block?.location.z },
                1,
                world.getDimension(block?.dimension.id)
            );

            if (block?.isValid() === true) {
                if (blockFound) {
                    if (!state) {
                        block?.setPermutation(block.permutation.withState(`cy_cr:on`, true));
                    };
                    block?.setPermutation(block.permutation.withState(`cy_cr:on_by_other`, false));
                    onStart(block, 0, cardinal);
                } else {
                    if (state && !onByOther) {
                        block?.setPermutation(block.permutation.withState(`cy_cr:on`, false));
                        onStart(block, 0, cardinal, `stop`);
                    }
                }
            }
        }
    };
    if (fullMessageCooldown > 0) {
        block.setPermutation(block.permutation.withState(`cy_cr:full_message_cooldown`, fullMessageCooldown - 1))
    };
    if (state && cardinal) {
        if (spawnItemCooldown > 0) {
            block.setPermutation(block.permutation.withState(`cy_cr:spawn_item_cooldown`, spawnItemCooldown - 1));
        };

        const minDistance = 1.0;
        const maxDistance = 6.5;
        const distanceHor = 1.5;
        let behindMinPos = { x: 0, y: 0, z: 0 };
        let behindMaxPos = { x: 0, y: 0, z: 0 };
        const frontDistance = 1.0;

        let directionX = 0;
        let directionZ = 0;
        let frontBlockPos = 0;

        switch (cardinal) {
            case 'north':
                behindMinPos = { x: block.center().x - distanceHor, y: block.center().y - 1, z: block.center().z + minDistance };
                behindMaxPos = { x: block.center().x + distanceHor, y: block.center().y + 1, z: block.center().z + maxDistance };
                directionZ = -1;
                frontBlockPos = { x: block.center().x, y: block.center().y, z: block.center().z - frontDistance };
                break;
            case 'south':
                behindMinPos = { x: block.center().x - distanceHor, y: block.center().y - 1, z: block.center().z - maxDistance };
                behindMaxPos = { x: block.center().x + distanceHor, y: block.center().y + 1, z: block.center().z - minDistance };
                directionZ = 1;
                frontBlockPos = { x: block.center().x, y: block.center().y, z: block.center().z + frontDistance };
                break;
            case 'west':
                behindMinPos = { x: block.center().x + minDistance, y: block.center().y - 1, z: block.center().z - distanceHor };
                behindMaxPos = { x: block.center().x + maxDistance, y: block.center().y + 1, z: block.center().z + distanceHor };
                directionX = -1;
                frontBlockPos = { x: block.center().x - frontDistance, y: block.center().y, z: block.center().z };
                break;
            case 'east':
                behindMinPos = { x: block.center().x - maxDistance, y: block.center().y - 1, z: block.center().z - distanceHor };
                behindMaxPos = { x: block.center().x - minDistance, y: block.center().y + 1, z: block.center().z + distanceHor };
                directionX = 1;
                frontBlockPos = { x: block.center().x + frontDistance, y: block.center().y, z: block.center().z };
                break;
        }

        if (spawnItemCooldown === 0 && block?.typeId === `cy_cr:item_conveyor_end`) {
            const entitiesBehind = block.dimension.getEntities({
                location: { x: (behindMinPos.x + behindMaxPos.x) / 2, y: block.center().y + 0.5, z: (behindMinPos.z + behindMaxPos.z) / 2 },
                maxDistance: maxDistance - minDistance,
                excludeFamilies: ['despawn', 'despawnable'],
                families: [`cy_cr:has_openable_container`, `cy_cr:machine`]
            });

            const entitiesInRange = entitiesBehind.filter(entity => {
                const pos = entity.location;
                return (
                    pos.x >= behindMinPos.x && pos.x <= behindMaxPos.x &&
                    pos.y >= block.center().y - 1 && pos.y <= block.center().y + 1 &&
                    pos.z >= behindMinPos.z && pos.z <= behindMaxPos.z
                );
            });

            entitiesInRange.forEach(entity => {
                let coords;
                let chestPos;

                if (entity.typeId !== `cy_cr:tear_farm` && entity.typeId !== `cy_cr:bin` && entity.typeId !== `cy_cr:cake_farm`) {
                    coords = { x: 0, y: 0, z: -3 };
                    chestPos = Vec3.getLocalCoords(entity, coords);
                } else if (entity.typeId === `cy_cr:bin`) {
                    coords = { x: 0, y: 0, z: 2 };
                    chestPos = Vec3.getLocalCoords(entity, coords);
                } else if (entity.typeId === `cy_cr:tear_farm`) {
                    coords = { x: 0, y: 0, z: -5 };
                    chestPos = Vec3.getLocalCoords(entity, coords);
                } else if (entity.typeId === `cy_cr:cake_farm`) {
                    coords = { x: 0, y: 0, z: -4 };
                    chestPos = Vec3.getLocalCoords(entity, coords);
                }

                const thisBlock = entity.dimension.getBlock(chestPos);
                //entity.dimension.spawnParticle(`minecraft:lava_particle`, chestPos)
                const hasSeeds = entity?.getProperty(`cy_cr:has_seeds`) ?? 0;
                const wheatSeeds = entity?.getProperty(`cy_cr:wheat_seeds`) ?? 0;
                const berrySeeds = entity?.getProperty(`cy_cr:berry_seeds`) ?? 0;
                const sugarSeeds = entity?.getProperty(`cy_cr:sugar_seeds`) ?? 0;

                if (thisBlock && thisBlock.typeId === `cy_cr:item_conveyor_end`) {
                    const inv = entity?.getComponent("inventory");
                    const container = inv?.container;
                    thisBlock.setPermutation(thisBlock.permutation.withState(`cy_cr:connected`, true));

                    if (hasSeeds !== false && wheatSeeds !== false && berrySeeds !== false && sugarSeeds !== false) {
                        const timeOut = system.runTimeout(() => {
                            if (entity?.isValid() === true) {
                                const collecting = entity?.getProperty(`cy_cr:collecting`) ?? 0;
                                if (collecting) {
                                    system.clearRun(timeOut);
                                    return;
                                };
                                let item;

                                for (let i = 0; i < inv.inventorySize; i++) {
                                    const invItem = container.getItem(i);
            
                                    if (invItem) {
                                        item = invItem;
                                        container.setItem(i, undefined);
                                        break;
                                    }
                                }
            
                                if (item) {
                                    block?.setPermutation(block.permutation.withState(`cy_cr:spawn_item_cooldown`, 5));
                                    const itemEnt = block.dimension.spawnItem(item, { x: block.center().x, y: block.center().y + 0.5, z: block.center().z });
                                    world.playSound(`random.pop`, itemEnt.location);
                                    const itemVel = itemEnt.getVelocity();
                                    itemEnt.applyImpulse({ x: -itemVel.x, y: -itemVel.y, z: -itemVel.z });
                                }
                            } else system.clearRun(timeOut)
                        }, 2)
                    }
                }
            });

            if (entitiesBehind.length === 0 || entitiesInRange === 0) {
                block.setPermutation(block.permutation.withState(`cy_cr:connected`, false))
            }
        }

        moveEntities(block, directionX, directionZ, cardinal, frontBlockPos);
    }
}
/**
 * 
 * @param {Block} block 
 * @param {Number} directionX 
 * @param {Number} directionZ 
 * @param {String} cardinal 
 * @param {Vec3} frontBlockPos 
 */
function moveEntities(block, directionX, directionZ, cardinal, frontBlockPos) {
    let dirY = 0;
    let dirX = directionX;
    let dirZ = directionZ;

    let minPos = {
        x: block.center().x - 0.5,
        y: block.center().y - 0.5,
        z: block.center().z - 0.5,
    };
    let maxPos = {
        x: block.center().x + 0.5,
        y: block.center().y + 0.5,
        z: block.center().z + 0.5,
    };

    if (block.typeId === `cy_cr:item_conveyor_corner`) {
        if (cardinal === `north` || cardinal === `south`) {
            minPos.x += 0.3;
            maxPos.x -= 0.3;
        };
        if (cardinal === `west` || cardinal === `east`) {
            minPos.z += 0.3;
            maxPos.z -= 0.3;
        }
    };
    if (block.typeId === `cy_cr:item_conveyor_middle` || block.typeId === `cy_cr:item_conveyor_end` || block.typeId === `cy_cr:item_conveyor_45_degreess`) {
        if (block.typeId === `cy_cr:item_conveyor_45_degreess`) {
            dirY = 1;
            minPos.y -= 0.5;
            maxPos.y += 1.0
        };
        if (cardinal === `north`) {
            minPos.z -= 0.3;
        };
        if (cardinal === `south`) {
            maxPos.z += 0.3
        }
        if (cardinal === `west`) {
            minPos.x -= 0.3;
        };
        if (cardinal === `east`) {
            maxPos.x += 0.3
        }
    }

    const entities = block.dimension.getEntities({
        location: { x: block.center().x, y: block.center().y + 0.5, z: block.center().z },
        maxDistance: 2,
        excludeFamilies: ['inanimate', 'despawn', 'despawnable'],
    });

    entities.forEach((entity) => {
        const pos = entity.location;

        if (pos.x >= minPos.x && pos.x <= maxPos.x &&
            pos.y >= minPos.y && pos.y < maxPos.y &&
            pos.z >= minPos.z && pos.z <= maxPos.z) {

            const velocity = entity.getVelocity();
            if (block.permutation.getState(`cy_cr:mirrored`) === true) {
                dirY = -dirY;
            };
            if (entity?.typeId !== 'minecraft:player') {
                entity?.applyImpulse({
                    x: (dirX * 0.1) - velocity.x,
                    y: (dirY * 0.2) - velocity.y,
                    z: (dirZ * 0.1) - velocity.z,
                });
            } else {
                entity?.applyKnockback(dirX, dirZ, 0.3, (dirY * 0.2));
            }
            if (block?.typeId === `cy_cr:item_conveyor_end`) {
                const distanceToEnd = 0.5;

                if (Math.abs(pos.x - (block.center().x + dirX * 0.5)) <= distanceToEnd && Math.abs(pos.z - (block.center().z + dirZ * 0.5)) <= distanceToEnd) {

                    conveyorEnd(block, entity, frontBlockPos);
                }
            }
        }
    });
}
/**
 * 
 * @param {Block} block 
 * @param {Entity} entity 
 */
function conveyorEnd(block, entity, frontBlockPos) {
    if (entity?.typeId === `minecraft:item`) {
        const item = entity?.getComponent("item").itemStack;
        const blockFront = block.dimension.getBlock(frontBlockPos);

        if (blockFront) {
            const container = blockFront.getComponent("inventory")?.container;

            if (container && blockFront?.typeId !== `minecraft:jukebox`) {
                const fullMessageCooldown = block.permutation.getState(`cy_cr:full_message_cooldown`) ?? 0;
                let foundSlot = false;

                for (let i = 0; i < container.size; i++) {
                    const contItem = container.getItem(i);

                    if (!contItem || contItem.typeId === item.typeId) {
                        if (!contItem) {
                            container.addItem(item);
                            world.playSound(`random.pop`, entity.location);
                            entity?.remove();
                            foundSlot = true;
                            break;
                        }
                        if (contItem.typeId === item.typeId) {
                            const contItemAmountDiff = contItem.maxAmount - contItem.amount;
                            if (item.amount <= contItemAmountDiff) {
                                container.addItem(item);
                                world.playSound(`random.pop`, entity.location);
                                entity?.remove();
                                foundSlot = true;
                                break;
                            }
                        }
                    }
                }

                if (!foundSlot && fullMessageCooldown === 0) {
                    isFull();
                }
                function isFull() {
                    block.setPermutation(block.permutation.withState(`cy_cr:full_message_cooldown`, 15));
                    block.setPermutation(block.permutation.withState(`cy_cr:on`, false));
                    const players = block.dimension.getPlayers({ location: block.center(), maxDistance: 10 });
                    players.forEach(player => {
                        player.onScreenDisplay.setActionBar({ translate: `translate.cy_cr.item_conveyor.chest_full` });
                        world.playSound(`note.banjo`, block.center(), { pitch: 0.5 });
                    });
                }
            } else return;
        }
    }
};
/**
 * 
 * @param {Block} block
 * @param {Number} i
 * @param {String} cardinal
 */
export function onStart(block, i, cardinal, message) {
    let north;
    let south;
    let newCardinal = cardinal;

    switch (cardinal) {
        case `north`:
            if (block.typeId !== `cy_cr:item_conveyor_45_degreess` && block.typeId !== `cy_cr:item_conveyor_corner`) {
                north = block.north(1);
                south = block.south(1);
                const down = north.below(1);
                const down2 = south.below(1);

                if (down.typeId === `cy_cr:item_conveyor_45_degreess`) {
                    north = down;
                };
                if (down2.typeId === `cy_cr:item_conveyor_45_degreess`) {
                    south = down2;
                }
            } else if (block.typeId === `cy_cr:item_conveyor_45_degreess`) {
                north = block.north(1).above(1);
                south = block.south(1).above(1);
                if (north.typeId === `minecraft:air`) {
                    north = block.north(1);
                    if (north.typeId === `minecraft:air`) {
                        north = block.north(1).below(1);
                    }
                };
                if (south.typeId === `minecraft:air`) {
                    south = block.south(1);
                    if (south.typeId === `minecraft:air`) {
                        south = block.south(1).below(1);
                    }
                }
            } else if (block.typeId === `cy_cr:item_conveyor_corner`) {
                const mirrored = block.permutation.getState(`cy_cr:mirrored`);
                if (mirrored) {
                    north = block.east(1);
                    newCardinal = `east`
                } else {
                    north = block.west(1);
                    newCardinal = `west`
                }
                south = block.south(1)
            }
            break;
        case `south`:
            if (block.typeId !== `cy_cr:item_conveyor_45_degreess` && block.typeId !== `cy_cr:item_conveyor_corner`) {
                north = block.south(1);
                south = block.north(1);
                const down = north.below(1);
                const down2 = south.below(1);

                if (down.typeId === `cy_cr:item_conveyor_45_degreess`) {
                    north = down;
                };
                if (down2.typeId === `cy_cr:item_conveyor_45_degreess`) {
                    south = down2;
                }
            } else if (block.typeId === `cy_cr:item_conveyor_45_degreess`) {
                north = block.south(1).above(1);
                south = block.north(1).above(1);
                if (north.typeId === `minecraft:air`) {
                    north = block.south(1);
                    if (north.typeId === `minecraft:air`) {
                        north = block.south(1).below(1);
                    }
                };
                if (south.typeId === `minecraft:air`) {
                    south = block.north(1);
                    if (south.typeId === `minecraft:air`) {
                        south = block.north(1).below(1);
                    }
                };
            } else if (block.typeId === `cy_cr:item_conveyor_corner`) {
                const mirrored = block.permutation.getState(`cy_cr:mirrored`);
                if (mirrored) {
                    north = block.west(1);
                    newCardinal = `west`
                } else {
                    north = block.east(1);
                    newCardinal = `east`
                }
                south = block.north(1)
            }
            break;
        case `east`:
            if (block.typeId !== `cy_cr:item_conveyor_45_degreess` && block.typeId !== `cy_cr:item_conveyor_corner`) {
                north = block.east(1);
                south = block.west(1);
                const down = north.below(1);
                const down2 = south.below(1);

                if (down.typeId === `cy_cr:item_conveyor_45_degreess`) {
                    north = down;
                };
                if (down2.typeId === `cy_cr:item_conveyor_45_degreess`) {
                    south = down2;
                }
            } else if (block.typeId === `cy_cr:item_conveyor_45_degreess`) {
                north = block.east(1).above(1);
                south = block.west(1).above(1);
                if (north.typeId === `minecraft:air`) {
                    north = block.east(1);
                    if (north.typeId === `minecraft:air`) {
                        north = block.east(1).below(1);
                    };
                };
                if (south.typeId === `minecraft:air`) {
                    south = block.west(1);
                    if (south.typeId === `minecraft:air`) {
                        south = block.west(1).below(1)
                    }
                }
            } else if (block.typeId === `cy_cr:item_conveyor_corner`) {
                const mirrored = block.permutation.getState(`cy_cr:mirrored`);
                if (mirrored) {
                    north = block.south(1);
                    newCardinal = `south`
                } else {
                    north = block.north(1);
                    newCardinal = `north`
                }
                south = block.west(1)
            }
            break;
        case `west`:
            if (block.typeId !== `cy_cr:item_conveyor_45_degreess` && block.typeId !== `cy_cr:item_conveyor_corner`) {
                north = block.west(1);
                south = block.east(1);
                const down = north.below(1);
                const down2 = south.below(1);

                if (down.typeId === `cy_cr:item_conveyor_45_degreess`) {
                    north = down;
                };
                if (down2.typeId === `cy_cr:item_conveyor_45_degreess`) {
                    south = down2;
                }
            } else if (block.typeId === `cy_cr:item_conveyor_45_degreess`) {
                north = block.west(1).above(1);
                south = block.east(1).above(1);
                if (north.typeId === `minecraft:air`) {
                    north = block.west(1);
                    if (north.typeId === `minecraft:air`) {
                        north = block.west(1).below(1);
                    };
                };
                if (south.typeId === `minecraft:air`) {
                    south = block.east(1);
                    if (south.typeId === `minecraft:air`) {
                        south = block.east(1).below(1);
                    }
                }
            } else if (block.typeId === `cy_cr:item_conveyor_corner`) {
                const mirrored = block.permutation.getState(`cy_cr:mirrored`);
                if (mirrored) {
                    north = block.north(1);
                    newCardinal = `north`
                } else {
                    north = block.south(1);
                    newCardinal = `south`
                }
                south = block.east(1)
            }
            break;
    };
    //north.dimension.spawnParticle(`minecraft:basic_smoke_particle`, north.center())
    //south.dimension.spawnParticle(`minecraft:basic_flame_particle`, south.center())

    if (i < 8) {
        if (message === undefined) {
            if (north) {
                if (north.typeId.startsWith(`cy_cr:`) && north.typeId.includes(`item_conveyor`)) {
                    const northState = north.permutation.getState(`cy_cr:on`);
                    if (!northState) {
                        north.setPermutation(north.permutation.withState(`cy_cr:on`, true));
                        north.setPermutation(north.permutation.withState(`cy_cr:on_by_other`, true));
                    }
                    onStart(north, i + 1, newCardinal);
                }
            }
            // Activar bloques hacia el sur
            if (south) {
                if (south.typeId.startsWith(`cy_cr:`) && south.typeId.includes(`item_conveyor`)) {
                    const southState = south.permutation.getState(`cy_cr:on`);
                    if (!southState) {
                        south.setPermutation(south.permutation.withState(`cy_cr:on`, true));
                        south.setPermutation(south.permutation.withState(`cy_cr:on_by_other`, true));
                    }
                    onStart(south, i + 1, newCardinal);
                }
            }
        } else if (message === `stop`) {
            if (north) {
                if (north.typeId.startsWith(`cy_cr:`) && north.typeId.includes(`item_conveyor`)) {
                    const northState = north.permutation.getState(`cy_cr:on`);
                    if (northState) {
                        north.setPermutation(north.permutation.withState(`cy_cr:on`, false));
                        north.setPermutation(north.permutation.withState(`cy_cr:on_by_other`, false));
                    }
                    onStart(north, i + 1, newCardinal, `stop`);
                }
            }
            // Detener bloques hacia el sur
            if (south) {
                if (south.typeId.startsWith(`cy_cr:`) && south.typeId.includes(`item_conveyor`)) {
                    const southState = south.permutation.getState(`cy_cr:on`);
                    if (southState) {
                        // Desactivar bloque activo
                        south.setPermutation(south.permutation.withState(`cy_cr:on`, false));
                        south.setPermutation(south.permutation.withState(`cy_cr:on_by_other`, false));
                    }
                    onStart(south, i + 1, newCardinal, `stop`);
                }
            }
        }
    }
};