import * as mc from "@minecraft/server";
import * as racoAPI from "../raco-API";
import { hasRedstonePower } from "../hasRedstonePower";

mc.world.beforeEvents.worldInitialize.subscribe(xZ => {
    xZ.blockComponentRegistry.registerCustomComponent('vtng_rt:intangible_door', {
        onPlayerInteract: async event => {
            const { block, dimension } = event;
            const isActive = block.permutation.getState('vtng_rt:on');
            const sides = ['north', 'south', 'east', 'west', 'above', 'below'];
            const pendingBlocks = [block];
            const visitedBlocks = new Set([JSON.stringify(block)]);
            while (pendingBlocks.length > 0) {
                const block = pendingBlocks.shift();
                for (let side of sides) {
                    const newBlock = block[side]();
                    if (newBlock.typeId == 'vtng_rt:intangible_door' && !visitedBlocks.has(JSON.stringify(newBlock))) {
                        pendingBlocks.push(newBlock);
                        visitedBlocks.add(JSON.stringify(newBlock));
                    };
                };
                if (!isActive) block.setPermutation(block.permutation.withState('vtng_rt:on', true)), dimension.playSound('block.bamboo.place', block.center(), {pitch: 0.6}), dimension.spawnParticle('vtng_rt:redstone_inp', block.center());
                else block.setPermutation(block.permutation.withState('vtng_rt:on', false)), dimension.playSound('block.bamboo.place', block.center(), {pitch: 0.6});
                await mc.system.waitTicks(1);
            };
        },
        onTick: event => {
            const { block, dimension } = event;
            block.setPermutation(block.permutation.withState('vtng_rt:on', false)), dimension.playSound('block.bamboo.place', block.center(), {pitch: 0.6});
        }
    });
    xZ.blockComponentRegistry.registerCustomComponent('vtng_rt:cardboard_box', {
        onPlayerInteract: async event => {
            const { block, dimension, player } = event;
            cardboardBoxInteract(player, block);
        }
    });
    xZ.blockComponentRegistry.registerCustomComponent('vtng_rt:redstone_capacitor', {
        onTick: event => {
            const { block, dimension } = event;
            const sides = ['north', 'south', 'east', 'west'];
            const capacitorKey = `${dimension.id},${block.x},${block.y},${block.z}`;
    
            if (redstoneCapacitor[capacitorKey] == undefined) {
                redstoneCapacitor[capacitorKey] = { value: 0, max: 0 };
            }
    
            const capacitor = redstoneCapacitor[capacitorKey];
    
            if (hasRedstonePower(block, ['north', 'south', 'west', 'east', 'below'], false)) {
                if (capacitor.value < 100) {
                    capacitor.value++;
                    capacitor.max = Math.max(capacitor.max, capacitor.value);
                }
                racoAPI.setPermutation(block, 'vtng_rt:capacitor_delay', 0);
            }
    
            if (block.getRedstonePower() <= 0 && capacitor.value > 0) {
                for (let side of sides) {
                    const repeater = block[side]();
                    if (repeater.typeId.includes('_repeater') && repeater.permutation.getState("minecraft:cardinal_direction") == invertFace[side]) {
                        block.dimension.runCommand(`setblock ${repeater.x} ${repeater.y} ${repeater.z} powered_repeater ["minecraft:cardinal_direction"="${invertFace[side]}", "repeater_delay"=${repeater.permutation.getState("repeater_delay")}]`);
                    }
                }
    
                const state = Math.min(3 - Math.floor((capacitor.value / capacitor.max) * 3), 3);
                racoAPI.setPermutation(block, 'vtng_rt:capacitor_delay', state);
    
                capacitor.value--;
            }
        }
    });
    
    
    
    
    xZ.blockComponentRegistry.registerCustomComponent('vtng_rt:player_sensor', {
        onTick: event => {
            const { block, dimension } = event;
            const players = block.dimension.getPlayers({ location: block.bottomCenter(), maxDistance: 7 });
            if (block.permutation.getState('vtng_rt:on') && !players[0]) block.setPermutation(block.permutation.withState('vtng_rt:on', false));
            if (!block.permutation.getState('vtng_rt:on') && players[0]) block.setPermutation(block.permutation.withState('vtng_rt:on', true));
            if (!players[0]) return;
            const sides = ['north', 'south', 'east', 'west'];
            for (let side of sides) {
                const repeater = block[side]();
                if (repeater.typeId.includes('_repeater') && repeater.permutation.getState("minecraft:cardinal_direction") == invertFace[side]) {
                    block.dimension.runCommand(`setblock ${repeater.x} ${repeater.y} ${repeater.z} powered_repeater ["minecraft:cardinal_direction"="${invertFace[side]}", "repeater_delay"=${repeater.permutation.getState("repeater_delay")}]`);
                };
            };
        }
    });
});

const redstoneCapacitor = {};

mc.world.beforeEvents.playerBreakBlock.subscribe((data) => {
    const player = data.player;
    const item = data.itemStack;
    const block = data.block;
    cardboardBreak(player, block, item);
});

mc.world.beforeEvents.itemUseOn.subscribe((data) => {
    const player = data.source;
    const item = data.itemStack;
    const block = data.block;
    cardBoardItemUse(player, block, item, data);
});

export function cardboardBoxInteract(player, block) {
    if (block?.typeId == 'vtng_rt:cardboard_box' && player?.isSneaking) {
        mc.system.run(() => {
            const property = mc.world.getDynamicProperty(`${block.dimension.id},${block.x},${block.y},${block.z}`)
            if (property) {
                //console.warn(property)
                const structureTest = block.dimension.runCommand(`structure load "${property}" ${block.x} ${block.y} ${block.z}`)?.successCount
                if (structureTest > 0) {
                    if (block.typeId == 'vtng_rt:single_chest') {
                        block.dimension.runCommand(`setblock ${block.x} ${block.y} ${block.z} chest`)
                        const entities = block.dimension.getEntities({ type: 'vtng_rt:recovery_chest', location: block.center(), maxDistance: 0.5, closest: 1 })
                        for (const entity of entities) {
                            const connectedChest = block
                            const entityB = entity
                            if (connectedChest && entityB) {
                                const entityBContainer = entityB.getComponent('inventory')?.container
                                for (let i = 0; i < entityBContainer?.size; i++) {
                                    const thisItem = entityBContainer.getItem(i)
                                    if (thisItem) {
                                        entityBContainer.transferItem(i, connectedChest.getComponent('inventory')?.container)
                                    }
                                }
                                entityB.remove()
                            }
                        }
                    }
                    const dropItem = new mc.ItemStack('vtng_rt:cardboard_box')
                    block.dimension.playSound('use.cloth', block.center())
                    block.dimension.spawnItem(dropItem, block.center())
                    block.dimension.runCommand(`structure delete "${property}"`)
                } else {
                    //console.warn('hasntStructure')
                }
            }
        })
    }
}


export function cardBoardItemUse(player, block, item, data) {
    if (item?.typeId == 'vtng_rt:cardboard_box') {
        if (!item?.getLore()?.length) {
            if (block?.typeId != 'minecraft:air') {
                if (!player.isSneaking && block?.typeId != 'vtng_rt:cardboard_box') {
                    data.cancel = true
                    mc.system.run(() => {
                        if (!player.hasTag('using')) {
                            player.addTag('using')
                            const randomId = racoAPI.generateRandomID(20)
                            if (block?.typeId == 'minecraft:chest') {
                                const thisContainer = block.getComponent('inventory')?.container
                                if (thisContainer?.size == 54) {
                                    let chestFaces = []
                                    if (block.permutation.getState("minecraft:cardinal_direction") == 'north' || block.permutation.getState("minecraft:cardinal_direction") == 'south') {
                                        chestFaces = [
                                            block.west(),
                                            block.east()
                                        ]
                                    } else
                                        if (block.permutation.getState("minecraft:cardinal_direction") == 'west' || block.permutation.getState("minecraft:cardinal_direction") == 'east') {
                                            chestFaces = [
                                                block.north(),
                                                block.south()
                                            ]
                                        }
                                    for (const thisChest of chestFaces) {
                                        if (thisChest.typeId == block.typeId) {
                                            const direction = thisChest.permutation.getState('minecraft:cardinal_direction')
                                            if (thisChest.permutation.getState('minecraft:cardinal_direction') == block.permutation.getState("minecraft:cardinal_direction")) {
                                                const anotherContainer = thisChest.getComponent('inventory').container
                                                if (anotherContainer?.size == 54) {
                                                    var equal = true
                                                    for (let i = 0; i < 54; i++) {
                                                        let itemA = thisContainer.getItem(i)
                                                        let itemB = anotherContainer.getItem(i)
                                                        if (itemA?.typeId != itemB?.typeId) {
                                                            equal = false
                                                            break
                                                        }
                                                    }
                                                    if (equal == true) {
                                                        var connectedChest = thisChest
                                                        var entityA = block.dimension.spawnEntity('vtng_rt:recovery_chest', block.center())
                                                        var entityB = thisChest.dimension.spawnEntity('vtng_rt:recovery_chest', thisChest.center())
                                                        for (let i = 0; i < 54; i++) {
                                                            if (i < 27) {
                                                                transferToEntity(block, thisContainer, i, entityA)
                                                            } else if (i >= 27) {
                                                                transferToEntity(thisChest, anotherContainer, i, entityB)
                                                            }
                                                        }
                                                        function transferToEntity(block, container, i, entity) {
                                                            const thisItem = container?.getItem(i)
                                                            if (thisItem) {
                                                                container.transferItem(i, entity.getComponent('inventory')?.container)
                                                            }
                                                        }
                                                        block.dimension.runCommand(`setblock ${block.x} ${block.y} ${block.z} vtng_rt:single_chest`)
                                                        block.dimension.runCommand(`setblock ${thisChest.x} ${thisChest.y} ${thisChest.z} chest`)
                                                        racoAPI.setPermutation(thisChest, 'minecraft:cardinal_direction', direction)
                                                        break
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            player.runCommand(`structure save "structure:${randomId}" ${block.x} ${block.y} ${block.z} ${block.x} ${block.y} ${block.z} true disk`)
                            player.runCommand(`setblock ${block.x} ${block.y} ${block.z} vtng_rt:cardboard_box`)
                            block.dimension.playSound('use.cloth', block.center())
                            if (equal) {
                                if (connectedChest, entityB, entityA) {
                                    const entityBContainer = entityB.getComponent('inventory')?.container
                                    for (let i = 0; i < entityBContainer?.size; i++) {
                                        const thisItem = entityBContainer.getItem(i)
                                        if (thisItem) {
                                            entityBContainer.transferItem(i, connectedChest.getComponent('inventory')?.container)
                                        }
                                    }
                                    entityB.remove()
                                }
                            }
                            const entities = block.dimension.getEntitiesAtBlockLocation(block.center())
                            for (const entity of entities) {
                                entity?.remove()
                            }
                            mc.world.setDynamicProperty(`${block.dimension.id},${block.x},${block.y},${block.z}`, `structure:${randomId}`)
                            racoAPI.clearMainhand(player, 1)
                            //console.warn(mc.world.getDynamicProperty(`${block.dimension.id},${block.x},${block.y},${block.z}`))
                            mc.system.runTimeout(() => {
                                player.removeTag('using')
                            }, 5)
                        }
                    })
                }
            }
        } else {
            const blockFace = block[racoAPI.blockFaceToDirection(data.blockFace)]()
            mc.world.setDynamicProperty(`${blockFace.dimension.id},${blockFace.x},${blockFace.y},${blockFace.z}`, `${item.getLore()[1]}`)
            const property = mc.world.getDynamicProperty(`${blockFace.dimension.id},${blockFace.x},${blockFace.y},${blockFace.z}`)
            //console.warn(property)
        }
    }
}
export function cardboardBreak(player, block, item) {
    if (block?.typeId == 'vtng_rt:cardboard_box') {
        mc.system.run(() => {
            const property = mc.world.getDynamicProperty(`${block.dimension.id},${block.x},${block.y},${block.z}`)
            const structureTest = property ? block.dimension.runCommand(`structure load "${property}" ${block.x} -64 ${block.z}`)?.successCount : undefined
            if (structureTest > 0) {
                const entities = block.dimension.getEntities({ location: { x: block.x, y: -64, z: block.z }, maxDistance: 2 })
                for (const entity of entities) {
                    entity?.remove()
                }
                const dropItem = new mc.ItemStack('vtng_rt:cardboard_box')
                const structureBlockId = block.dimension.getBlock({ x: block.x, y: -64, z: block.z })?.typeId
                dropItem.setLore([`§r§7${racoAPI.transformKey(structureBlockId)}`, `${property}`])
                block.dimension.runCommand(`setblock ${block.x} -64 ${block.z} bedrock`)
                block.dimension.spawnItem(dropItem, block.center())
                block.dimension.playSound('use.cloth', block.center())
            } else if (player.getGameMode() == 'survival') {
                const dropItem = new mc.ItemStack('vtng_rt:cardboard_box')
                block.dimension.spawnItem(dropItem, block.center())
                block.dimension.playSound('use.cloth', block.center())
            }
        })
    }
}


const invertFace = { 'north': 'south', 'south': 'north', 'east': 'west', 'west': 'east', 'up': 'down', 'down': 'up' };

export const correctDirections = {
    'north': {
        north: 'north', south: 'south', east: 'east', west: 'west', above: 'above', below: 'below'
    },
    'south': {
        north: 'south', south: 'north', east: 'west', west: 'east', above: 'above', below: 'below'
    },
    'east': {
        north: 'east', south: 'west', east: 'south', west: 'north', above: 'above', below: 'below'
    },
    'west': {
        north: 'west', south: 'east', east: 'north', west: 'south', above: 'above', below: 'below'
    },
    'up': {
        north: 'above', south: 'below', east: 'east', west: 'west', above: 'south', below: 'north'
    },
    'down': {
        north: 'below', south: 'above', east: 'east', west: 'west', above: 'north', below: 'south'
    }
};