import { world } from "@minecraft/server"
import { ChannelKey } from './channel_key.js';



export class ItemTeleporterComponent {
    constructor() {
        this.onStepOn = this.onStepOn.bind(this);
        this.onPlayerInteract = this.onPlayerInteract.bind(this);

        this.impulseVector = { x: 0, y: 0, z: 0 };
        this.COLOR_DYE_LIST = [
            "minecraft:black_dye",
            "minecraft:blue_dye",
            "minecraft:brown_dye",
            "minecraft:cyan_dye",
            "minecraft:gray_dye",
            "minecraft:green_dye",
            "minecraft:light_blue_dye",
            "minecraft:light_gray_dye",
            "minecraft:lime_dye",
            "minecraft:magenta_dye",
            "minecraft:orange_dye",
            "minecraft:pink_dye",
            "minecraft:purple_dye",
            "minecraft:red_dye",
            "minecraft:white_dye",
            "minecraft:yellow_dye"
        ];
    }

    updateDynamicProperties(block, oldColorChannel, newColorChannel, tpIn) {
        const namespace = "pb_red";
        const transmittersKey = `${namespace}:transmitters`;
        const receiversKey = `${namespace}:receivers`;

        const blockLocation = { x: block.location.x, y: block.location.y, z: block.location.z };
        const blockDimension = block.dimension.id;
        const blockData = {
            state: tpIn ? "transmitter" : "receiver",
            colorChannel: newColorChannel,
            location: blockLocation,
            dimension: blockDimension
        };

        // Remove old properties
        const keys = [transmittersKey, receiversKey];
        keys.forEach(key => {
            let properties = JSON.parse(world.getDynamicProperty(key) || "[]");
            properties = properties.filter(prop => !(prop.location.x === blockLocation.x && prop.location.y === blockLocation.y && prop.location.z === blockLocation.z && prop.dimension === blockDimension));
            world.setDynamicProperty(key, JSON.stringify(properties));
        });

        // Add new property
        const key = tpIn ? transmittersKey : receiversKey;
        let properties = JSON.parse(world.getDynamicProperty(key) || "[]");
        properties.push(blockData);
        world.setDynamicProperty(key, JSON.stringify(properties));
    }

    removeDynamicProperties(block) {
        const namespace = "pb_red";
        const transmittersKey = `${namespace}:transmitters`;
        const receiversKey = `${namespace}:receivers`;

        const blockLocation = { x: block.location.x, y: block.location.y, z: block.location.z };
        const blockDimension = block.dimension.id;

        const keys = [transmittersKey, receiversKey];
        keys.forEach(key => {
            let properties = JSON.parse(world.getDynamicProperty(key) || "[]");
            properties = properties.filter(prop => !(prop.location.x === blockLocation.x && prop.location.y === blockLocation.y && prop.location.z === blockLocation.z && prop.dimension === blockDimension));
            world.setDynamicProperty(key, JSON.stringify(properties));
        });
    }

    onPlayerInteract(e) {
        const block = e.block;
        const player = e.player;
        const selectedSlot = player.selectedSlotIndex;
        const handItem = player.getComponent("inventory").container.getItem(selectedSlot);
        block.dimension.spawnParticle("pb_red:portal_idle", { x: block.location.x + 0.5, y: block.location.y + 0.5, z: block.location.z + 0.5 })

        if (handItem?.typeId == "pb_red:redstone_wrench") {
            block.dimension.runCommand(`playsound random.click @a ${block.location.x} ${block.location.y} ${block.location.z}`)

            const channelKey = new ChannelKey(block, null);
            channelKey.openUI(player)

            return;

        }

        const oldColorChannel = block.permutation.getState('pb_red:color_channel');
        const tpIn = block.permutation.getState('pb_red:tp_in');

        if (this.COLOR_DYE_LIST.includes(handItem?.typeId)) {
            const newColorChannel = this.COLOR_DYE_LIST.indexOf(handItem.typeId);
            block.setPermutation(block.permutation.withState('pb_red:color_channel', newColorChannel));
            player.runCommand(`clear @s ${handItem.typeId} 0 1`);
            block.dimension.runCommand(`playsound sign.ink_sac.use @a ${block.location.x} ${block.location.y} ${block.location.z}`)
            //   console.warn("channel set to : " + newColorChannel);
            this.updateDynamicProperties(block, oldColorChannel, newColorChannel, tpIn);
        } else {
            const newTpIn = !tpIn;
            block.dimension.runCommand(`playsound vr.stutterturn @a ${block.location.x} ${block.location.y} ${block.location.z}`)
            block.setPermutation(block.permutation.withState('pb_red:tp_in', newTpIn));
            const colorChannel = block.permutation.getState('pb_red:color_channel');
            this.updateDynamicProperties(block, oldColorChannel, colorChannel, newTpIn);
        }
    }

    getFrontandBack(direction, block) {
        let frontOffset, leftOffset;
        switch (direction) {
            case 'north':
                frontOffset = { x: 0, y: 0, z: -1 };
                leftOffset = { x: -1, y: 0, z: 0 };
                break;
            case 'south':
                frontOffset = { x: 0, y: 0, z: 1 };
                leftOffset = { x: 1, y: 0, z: 0 };
                break;
            case 'east':
                frontOffset = { x: 1, y: 0, z: 0 };
                leftOffset = { x: 0, y: 0, z: -1 };
                break;
            case 'west':
                frontOffset = { x: -1, y: 0, z: 0 };
                leftOffset = { x: 0, y: 0, z: 1 };
                break;
        }
        return { frontOffset, leftOffset };
    }

    onStepOn(e) {
        const block = e.block;
        const direction = block.permutation.getState('minecraft:cardinal_direction');
        const oppositeDirections = {
            'north': "south",
            'east': "west",
            'south': "north",
            'west': "east"
        };
        block.dimension.spawnParticle("pb_red:portal_idle", { x: block.location.x + 0.5, y: block.location.y + 0.5, z: block.location.z + 0.5 })

        const tpIn = block.permutation.getState('pb_red:tp_in');
        const finalDirection = tpIn ? direction : oppositeDirections[direction];

        let { frontOffset, leftOffset } = this.getFrontandBack(finalDirection, block);

        for (const aboveEntity of block.dimension.getEntitiesAtBlockLocation(block.location)) {
            if (aboveEntity.typeId === 'minecraft:player') {
                return;
            }

            aboveEntity.clearVelocity();
            this.impulseVector = { x: frontOffset.x / 3, y: frontOffset.y + 0.05, z: frontOffset.z / 3 };
            aboveEntity.applyImpulse(this.impulseVector);

            if (aboveEntity.typeId === "minecraft:item") {

                if (tpIn) {
                    const colorChannel = block.permutation.getState('pb_red:color_channel');
                    const receiversKey = `pb_red:receivers`;
                    const receivers = JSON.parse(world.getDynamicProperty(receiversKey) || "[]");

                    // Filter for the correct color channel and Key
                    const validReceivers = receivers.filter(receiver => {

                        const targetBlock = ChannelKey.constructBlock(receiver.location, receiver.dimension);
                        const channelKey = new ChannelKey(block, targetBlock);

                        return receiver.colorChannel === colorChannel && channelKey.channelConfirmed();
                    });


                    if (validReceivers.length > 0) {
                        const receiver = validReceivers[Math.floor(Math.random() * validReceivers.length)];

                        //   system.runTimeout(() => {
                        const targetDimensionInstance = world.getDimension(receiver.dimension);
                        block.dimension.spawnParticle("pb_red:portal_port", { x: block.location.x + 0.5, y: block.location.y + 0.5, z: block.location.z + 0.5 })
                        block.dimension.runCommand(`playsound mob.shulker.teleport @a ${block.location.x} ${block.location.y} ${block.location.z} 0.3`)
                        if (receiver.dimension == "minecraft:nether") {
                            aboveEntity.teleport({
                                x: receiver.location.x + 0.0625,
                                y: receiver.location.y + 0.5,
                                z: receiver.location.z + 0.0625
                            }, {
                                dimension: targetDimensionInstance
                            });
                        } else {
                            aboveEntity.teleport({
                                x: receiver.location.x + 0.5,
                                y: receiver.location.y + 0.5,
                                z: receiver.location.z + 0.5
                            }, {
                                dimension: targetDimensionInstance
                            });
                        }

                        //  }, 2)
                    } else {
                        aboveEntity.clearVelocity()
                    }
                }
            }
        }
    }
}