import { world, BlockPermutation, ItemStack } from "@minecraft/server"
import { ModalFormData } from "@minecraft/server-ui"
import { Vector } from './vector.js';
import { ChannelKey } from './channel_key.js';


export class RemoteControlledRedstoneComponent {
    constructor() {
        this.onTick = this.onTick.bind(this);
        this.onPlayerInteract = this.onPlayerInteract.bind(this);

        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"
        ];
    }

    getWirelessRedstoneData() {
        return JSON.parse(world.getDynamicProperty("pb_red:remote_controled_redtone_data") || "[]");
    }

    setWirelessRedstoneData(data) {
        world.setDynamicProperty("pb_red:remote_controled_redtone_data", JSON.stringify(data));
    }

    updateWirelessRedstoneData(block, colorChannel, isReceiver) {
        const locationStr = `${block.location.x},${block.location.y},${block.location.z}`;
        const key = new ChannelKey(block).getKey(block);
        let data = this.getWirelessRedstoneData();
        const keyChannel = `${colorChannel}:${key || "pb_red:null"}`;
        let channelData = data.find(d => d.channel === keyChannel);

        if (!channelData) {
            channelData = { channel: keyChannel, receivers: [], hasPower: false };
            data.push(channelData);
        }

        if (isReceiver) {
            if (!channelData.receivers.includes(locationStr)) {
                channelData.receivers.push(locationStr);
            }
        } else {
            channelData.receivers = channelData.receivers.filter(loc => loc !== locationStr);
        }

        this.setWirelessRedstoneData(data);
    }


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

        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);

        }

        if (this.COLOR_DYE_LIST.includes(handItem?.typeId)) {
            let colorChannel = this.COLOR_DYE_LIST.indexOf(handItem.typeId);
            block.setPermutation(block.permutation.withState('pb_red:color_channel', colorChannel));
            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 : " + colorChannel);
        }

        this.updateWirelessRedstoneData(block, block.permutation.getState('pb_red:color_channel'), true);
    }

    removeDynamicProperties(block) {
        const locationStr = `${block.location.x},${block.location.y},${block.location.z}`;
        let data = this.getWirelessRedstoneData();

        for (let channelData of data) {
            channelData.receivers = channelData.receivers.filter(loc => loc !== locationStr);
        }

        this.setWirelessRedstoneData(data);
    }
    getFrontandBack(direction, block) {
        let backBlock;
        switch (direction) {
            case 'north':
                backBlock = block.south();
                break;
            case 'south':
                backBlock = block.north();
                break;
            case 'east':
                backBlock = block.west();
                break;
            case 'west':
                backBlock = block.east();
                break;
        }
        return { backBlock };
    }
    onTick(e) {
        const block = e.block;
        const colorChannel = block.permutation.getState('pb_red:color_channel');
        const locationStr = `${block.location.x},${block.location.y},${block.location.z}`;
        const blockKey = new ChannelKey(block).getKey(block);
        const keyChannel = `${colorChannel}:${blockKey || "pb_red:null"}`;
        this.updateWirelessRedstoneData(block, colorChannel, true);

        let data = this.getWirelessRedstoneData();
        let channelData = data.find(d => d.channel === keyChannel);

        if (channelData && channelData.receivers.includes(locationStr)) {
            if (channelData.hasPower) {
                block.setPermutation(block.permutation.withState('pb_red:powered', true));
                const direction = block.permutation.getState('minecraft:cardinal_direction');
                const { backBlock } = this.getFrontandBack(direction, block);

                if (backBlock.permutation.matches("minecraft:unpowered_repeater") && backBlock.permutation.getState("minecraft:cardinal_direction") === direction) {
                    backBlock.setPermutation(BlockPermutation.resolve("minecraft:powered_repeater", { 'minecraft:cardinal_direction': direction }));
                }
            } else {
                try {
                    block.setPermutation(block.permutation.withState('pb_red:powered', false));

                } catch { }
            }
        } else {
            try {

                block.setPermutation(block.permutation.withState('pb_red:powered', false));
            } catch { }
        }
    }

}


export class RedstoneControllerComponent {
    constructor() {
        this.onUse = this.onUse.bind(this);

        this.Color_List = [
            "§0black",
            "§1blue",
            "brown",
            "§3cyan",
            "§8gray",
            "§2green",
            "§blight blue",
            "§7light gray",
            "§alime",
            "§5magenta",
            "§6orange",
            "§dpink",
            "§5purple",
            "§4red",
            "§fwhite",
            "§eyellow"
        ];
    }

    getWirelessRedstoneData() {
        return JSON.parse(world.getDynamicProperty("pb_red:remote_controled_redtone_data") || "[]");
    }

    setWirelessRedstoneData(data) {
        world.setDynamicProperty("pb_red:remote_controled_redtone_data", JSON.stringify(data));
    }

    onUse(e) {
        const player = e.source;
        const item = e.itemStack;
        const selectedSlot = player.selectedSlotIndex;
        const handItem = player.getComponent("inventory").container.getItem(selectedSlot);

        if (player.isSneaking) {

            const RedstoneControllerGUI = new ModalFormData()
                .title("Redstone Controller")
                .dropdown("Color Channel", this.Color_List, parseInt(item.typeId.split("_")[3]) - 1)
                .toggle("Assign Channel Key", false)
                .show(player).then((selec) => {
                    if (selec.canceled) return;

                    const colorChannel = selec.formValues[0];
                    const assignKey = selec.formValues[1];

                    if (handItem.typeId === item.typeId) {
                        const newItem = new ItemStack(`pb_red:redstone_controller_${colorChannel + 1}`, 1)
                        const controllerKey = item.getDynamicProperty("pb_red:channel_key") || null;
                        if (controllerKey !== null) newItem.setDynamicProperty("pb_red:channel_key", controllerKey)

                        player.getComponent("inventory").container.setItem(selectedSlot, newItem);

                        if (assignKey) {
                            const controllerKey = new ChannelKey();
                            controllerKey.openControllerUI(player, newItem);
                        }
                    }
                });
        } else {
            const colorChannel = parseInt(item.typeId.split('_').pop()) - 1;
            const controllerKey = item.getDynamicProperty("pb_red:channel_key") || null;

            const keyChannel = `${colorChannel}:${controllerKey || "pb_red:null"}`;
            let data = this.getWirelessRedstoneData();
            let channelData = data.find(d => d.channel === keyChannel);

            if (!channelData) {
                channelData = { channel: keyChannel, receivers: [], hasPower: false };
                data.push(channelData);
            }

            if (channelData.hasPower === false) {
                channelData.hasPower = true;
                player.onScreenDisplay.setActionBar(`Channel §l${this.Color_List[colorChannel]} ${(controllerKey !== "pb_red:null" && controllerKey !== null) ? `(key: ${controllerKey})` : ""}§r is now §2§lpowered`);
                player.dimension.runCommand(`playsound note.bell @a ${player.location.x} ${player.location.y} ${player.location.z}`);
            } else {
                channelData.hasPower = false;
                player.onScreenDisplay.setActionBar(`Channel §l${this.Color_List[colorChannel]} ${(controllerKey !== "pb_red:null" && controllerKey !== null) ? `(key: ${controllerKey})` : ""}§r is now §4§lunpowered`);
                player.dimension.runCommand(`playsound note.bit @a ${player.location.x} ${player.location.y} ${player.location.z}`);
            }

            this.setWirelessRedstoneData(data);
        }
    }

}


