import * as mc from "@minecraft/server";
import {hasRedstonePower} from "../hasRedstonePower"

mc.world.beforeEvents.worldInitialize.subscribe(xZ => {
    xZ.itemComponentRegistry.registerCustomComponent('vtng_rt:builder_wand', { onUseOn: event => { } });
    xZ.itemComponentRegistry.registerCustomComponent('vtng_rt:anti_gravity_block', {
        onUse: event => {
            const { itemStack, source } = event;
            const blockFromView = source.getBlockFromViewDirection({ maxDistance: 5 });
            if (blockFromView) {
                const previousBlock = blockFromView.block[blockFromView.face == 'Up' ? 'above' : blockFromView.face == 'Down' ? 'below' : blockFromView.face.toLowerCase()]();
                if (!previousBlock.isAir) return;
                previousBlock.setType('vtng_rt:anti_gravity_block');
                if (source.getGameMode() != 'creative') removeItem(source, 'vtng_rt:anti_gravity_block_item', 1);
            } else {
                const belowBlock = source.dimension.getBlock({ x: source.location.x, y: source.location.y - 1.2, z: source.location.z });
                if (!belowBlock.isAir) return;
                belowBlock.setType('vtng_rt:anti_gravity_block');
                if (source.getGameMode() != 'creative') removeItem(source, 'vtng_rt:anti_gravity_block_item', 1);
            };
        }
    });
    xZ.blockComponentRegistry.registerCustomComponent('vtng_rt:logic_gates', {
        onTick: event => {
            const {block, dimension} = event;
            const rotation = block.permutation.getState('minecraft:cardinal_direction');
            const frontBlock = block[rotation]();
            const leftBlock = block[correctDirections[rotation]['west']]();
            const rightBlock = block[correctDirections[rotation]['east']]();
            if (block.typeId == 'vtng_rt:logic_gate_or') {
                if (leftBlock.getRedstonePower() > 0 || rightBlock.getRedstonePower() > 0) {
                    if (frontBlock.typeId.includes('_repeater') && frontBlock.permutation.getState("minecraft:cardinal_direction") == invertFace[rotation]) {
                        block.dimension.runCommand(`setblock ${frontBlock.x} ${frontBlock.y} ${frontBlock.z} powered_repeater ["minecraft:cardinal_direction"="${invertFace[rotation]}", "repeater_delay"=${frontBlock.permutation.getState("repeater_delay")}]`);
                    };
                    if (!block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', true));
                } else if (block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', false));
            };
            if (block.typeId == 'vtng_rt:logic_gate_nor') {
                if (!leftBlock.getRedstonePower() && !rightBlock.getRedstonePower()) {
                    if (frontBlock.typeId.includes('_repeater') && frontBlock.permutation.getState("minecraft:cardinal_direction") == invertFace[rotation]) {
                        block.dimension.runCommand(`setblock ${frontBlock.x} ${frontBlock.y} ${frontBlock.z} powered_repeater ["minecraft:cardinal_direction"="${invertFace[rotation]}", "repeater_delay"=${frontBlock.permutation.getState("repeater_delay")}]`);
                    };
                    if (!block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', true));
                } else if (block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', false));
            };
            if (block.typeId == 'vtng_rt:logic_gate_and') {
                if (leftBlock.getRedstonePower() > 0 && rightBlock.getRedstonePower() > 0) {
                    if (frontBlock.typeId.includes('_repeater') && frontBlock.permutation.getState("minecraft:cardinal_direction") == invertFace[rotation]) {
                        block.dimension.runCommand(`setblock ${frontBlock.x} ${frontBlock.y} ${frontBlock.z} powered_repeater ["minecraft:cardinal_direction"="${invertFace[rotation]}", "repeater_delay"=${frontBlock.permutation.getState("repeater_delay")}]`);
                    };
                    if (!block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', true));
                } else if (block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', false));
            };
            if (block.typeId == 'vtng_rt:logic_gate_nand') {
                if (!leftBlock.getRedstonePower() || !rightBlock.getRedstonePower()) {
                    if (frontBlock.typeId.includes('_repeater') && frontBlock.permutation.getState("minecraft:cardinal_direction") == invertFace[rotation]) {
                        block.dimension.runCommand(`setblock ${frontBlock.x} ${frontBlock.y} ${frontBlock.z} powered_repeater ["minecraft:cardinal_direction"="${invertFace[rotation]}", "repeater_delay"=${frontBlock.permutation.getState("repeater_delay")}]`);
                    };
                    if (!block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', true));
                } else if (block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', false));
            };
            if (block.typeId == 'vtng_rt:logic_gate_xor') {
                if ((leftBlock.getRedstonePower() > 0 && !rightBlock.getRedstonePower()) || (!leftBlock.getRedstonePower() && rightBlock.getRedstonePower() > 0)) {
                    if (frontBlock.typeId.includes('_repeater') && frontBlock.permutation.getState("minecraft:cardinal_direction") == invertFace[rotation]) {
                        block.dimension.runCommand(`setblock ${frontBlock.x} ${frontBlock.y} ${frontBlock.z} powered_repeater ["minecraft:cardinal_direction"="${invertFace[rotation]}", "repeater_delay"=${frontBlock.permutation.getState("repeater_delay")}]`);
                    };
                    if (!block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', true));
                } else if (block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', false));
            };
            if (block.typeId == 'vtng_rt:logic_gate_xnor') {
                if (!leftBlock.getRedstonePower() && !rightBlock.getRedstonePower() || leftBlock.getRedstonePower() > 0 && rightBlock.getRedstonePower() > 0) {
                    if (frontBlock.typeId.includes('_repeater') && frontBlock.permutation.getState("minecraft:cardinal_direction") == invertFace[rotation]) {
                        block.dimension.runCommand(`setblock ${frontBlock.x} ${frontBlock.y} ${frontBlock.z} powered_repeater ["minecraft:cardinal_direction"="${invertFace[rotation]}", "repeater_delay"=${frontBlock.permutation.getState("repeater_delay")}]`);
                    };
                    if (!block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', true));
                } else if (block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', false));
            };
            if (block.typeId == 'vtng_rt:logic_gate_buffer') {
                if (block[invertFace[rotation]]().getRedstonePower() > 0) {
                    if (frontBlock.typeId.includes('_repeater') && frontBlock.permutation.getState("minecraft:cardinal_direction") == invertFace[rotation]) {
                        block.dimension.runCommand(`setblock ${frontBlock.x} ${frontBlock.y} ${frontBlock.z} powered_repeater ["minecraft:cardinal_direction"="${invertFace[rotation]}", "repeater_delay"=${frontBlock.permutation.getState("repeater_delay")}]`);
                    };
                    if (!block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', true));
                } else if (block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', false));
            };
            if (block.typeId == 'vtng_rt:logic_gate_not') {
                if (!block[invertFace[rotation]]().getRedstonePower()) {
                    if (frontBlock.typeId.includes('_repeater') && frontBlock.permutation.getState("minecraft:cardinal_direction") == invertFace[rotation]) {
                        block.dimension.runCommand(`setblock ${frontBlock.x} ${frontBlock.y} ${frontBlock.z} powered_repeater ["minecraft:cardinal_direction"="${invertFace[rotation]}", "repeater_delay"=${frontBlock.permutation.getState("repeater_delay")}]`);
                    };
                    if (!block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', true));
                } else if (block.permutation.getState('vtng_rt:on')) block.setPermutation(block.permutation.withState('vtng_rt:on', false));
            };
        }
    });
});

mc.system.runInterval(() => {
    const players = mc.world.getAllPlayers();
    players.forEach(player => {
        const itemMainHand = player.getComponent('equippable')?.getEquipment("Mainhand");
        if (itemMainHand?.typeId == 'vtng_rt:builder_wand') {
            const blockFromView = player.getBlockFromViewDirection({ maxDistance: 9 });
            mc.system.runTimeout(() => { builderWand(blockFromView?.block, blockFromView?.face, player) }, 3)
        };
    });
});

mc.world.afterEvents.playerPlaceBlock.subscribe(xZ => {
    const { block, dimension, player } = xZ;
    const itemOffHand = player.getComponent('equippable')?.getEquipment("Offhand");
    if (itemOffHand?.typeId == 'vtng_rt:electrician_gloves' && block.typeId == 'minecraft:redstone_wire' && Math.random() > 0.75 && player.getGameMode() != 'creative') {
        const playerInv = player.getComponent('minecraft:inventory').container;
        const redstoneBack = new mc.ItemStack('minecraft:redstone', 1);
        playerInv.addItem(redstoneBack);
    };
});

mc.world.beforeEvents.itemUseOn.subscribe(event => {
    const { block, itemStack, source, blockFace } = event;
    if (itemStack.typeId == 'vtng_rt:hand_piston') {
        mc.system.run(() => {
            const cooldown = itemStack.getComponent('minecraft:cooldown').getCooldownTicksRemaining(source);
            if (cooldown < 9 || block.typeId == 'minecraft:bedrock') return;
            const nextBlock = block[blockFace == 'Up' ? 'below' : blockFace == 'Down' ? 'above' : invertFace[blockFace.toLowerCase()]]();
            if (nextBlock.isAir) {
                mc.world.structureManager.createFromWorld(`vtng:${source.id},${block.x},${block.y},${block.z}`, block.dimension, block.location, block.location, { includeEntities: false, saveMode: "Memory" });
                block.setType('minecraft:air');
                mc.world.structureManager.place(`vtng:${source.id},${block.x},${block.y},${block.z}`, block.dimension, nextBlock.location);
                mc.world.structureManager.delete(`vtng:${source.id},${block.x},${block.y},${block.z}`);
                block.dimension.playSound('tile.piston.in', block.center())
            };
        });
    };
    if (itemStack.typeId == 'vtng_rt:sticky_hand_piston') {
        mc.system.run(() => {
            const cooldown = itemStack.getComponent('minecraft:cooldown').getCooldownTicksRemaining(source);
            if (cooldown < 9 || block.typeId == 'minecraft:bedrock') return;
            const previousBlock = block[blockFace == 'Up' ? 'above' : blockFace == 'Down' ? 'below' : blockFace.toLowerCase()]();
            if (previousBlock.isAir) { //&& source.isSneaking
                mc.world.structureManager.createFromWorld(`vtng:${source.id},${block.x},${block.y},${block.z}`, block.dimension, block.location, block.location, { includeEntities: false, saveMode: "Memory" });
                block.setType('minecraft:air');
                mc.world.structureManager.place(`vtng:${source.id},${block.x},${block.y},${block.z}`, block.dimension, previousBlock.location);
                mc.world.structureManager.delete(`vtng:${source.id},${block.x},${block.y},${block.z}`);
                block.dimension.playSound('tile.piston.out', block.center())
            };
        });
    };
    if (itemStack.typeId == 'vtng_rt:builder_wand') {
        mc.system.run(() => {
            const itemCooldown = itemStack.getComponent('minecraft:cooldown');
            if (itemCooldown.getCooldownTicksRemaining(source) == 0) {
                itemCooldown.startCooldown(source);
                builderWand(block, blockFace, source, true);
            };
        });
    };
});

function builderWand(block, thisFace, player, place) {
    if (!block || !thisFace) return;
    if (block.typeId == 'minecraft:bedrock' || block.typeId == 'vtng_rt:mechanical_crafter') return;
    let face = thisFace.toLowerCase();
    if (face == 'up') face = 'above'; if (face == 'down') face = 'below';
    const pendingBlocks = [block];
    const visitedBlocks = [`${block.x},${block.y},${block.z}`];
    let numBlocks = 0;

    let checkSides = [];
    if (face == 'above' || face == 'below') checkSides = ['north', 'south', 'west', 'east']; //, 'north.west', 'north.east', 'south.west', 'south.east's
    if (face == 'north' || face == 'south') checkSides = ['above', 'below', 'west', 'east']; //, 'above.west', 'above.east', 'below.west', 'below.east'
    if (face == 'west' || face == 'east') checkSides = ['above', 'below', 'north', 'south']; //, 'above.north', 'above.south', 'below.north', 'below.south'

    while (pendingBlocks.length > 0 && numBlocks <= 24) {
        const block = pendingBlocks.shift();
        for (let side of checkSides) {
            const newBlock = block[side]();
            if (newBlock?.typeId == block.typeId && newBlock[face]()?.isAir && !visitedBlocks.includes(`${newBlock.x},${newBlock.y},${newBlock.z}`)) {
                visitedBlocks.push(`${newBlock.x},${newBlock.y},${newBlock.z}`);
                pendingBlocks.push(newBlock);
            };
        };
        if (place) {
            const playerInv = player.getComponent('minecraft:inventory').container;
            let hasItem = false;
            for (let i = 0; i < playerInv.size; i++) {
                const item = playerInv.getItem(i);
                if (item?.typeId == block.typeId) {
                    const newItem = new mc.ItemStack(item?.typeId, item.amount > 1 ? item.amount - 1 : 1);
                    playerInv.getSlot(i).setItem(item.amount > 1 ? newItem : undefined);
                    hasItem = true;
                    break;
                };
            };
            if (!hasItem && player.getGameMode() != 'creative') {
                player.runCommand(`titleraw @s actionbar {"rawtext": [{ "translate": "vntg_rt.builder_wand_block_missing.warn" }]}`);
                return;
            };
            player.playSound('block.end_portal_frame.fill', { volume: 1, pitch: 3 });
            block.dimension.runCommand(`setblock ${block[face]().x} ${block[face]().y} ${block[face]().z} ${block.typeId}`);
        };
        block.dimension.spawnParticle(`vtng_rt:selection_${face}`, block.center());
        numBlocks++;
    };
};

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

function removeItem(player, searchId, amount) {
    const playerInv = player.getComponent('minecraft:inventory').container;
    for (let slot = 0; slot < playerInv.size; slot++) {
        const itemSearched = playerInv.getItem(slot);
        if (itemSearched?.typeId == searchId) {
            if (itemSearched.amount < amount) return;
            const replacementItem = new mc.ItemStack(itemSearched?.typeId, itemSearched.amount > amount ? itemSearched.amount - amount : 1);
            if (amount) playerInv.setItem(slot, itemSearched.amount > amount ? replacementItem : undefined);
            return true;
        };
    };
};

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'
    }
};