import { world, system, BlockPermutation } from "@minecraft/server"
import { ModalFormData } from "@minecraft/server-ui"



export class CustomRepeaterComponent {
    constructor() {
        this.onTick = this.onTick.bind(this);
        this.onPlayerInteract = this.onPlayerInteract.bind(this);
        this.unloadedChunkTimeToActivate = 0;
        this.DYNAMIC_PROPERTY_NAME = "pb_red:custom_repeater_data";
        this.REDSTONE_POWER_BLOCKS = [
            { id: "minecraft:redstone_wire", state: "redstone_signal" },
            { id: "minecraft:powered_repeater", state: "minecraft:cardinal_direction" },
            { id: "minecraft:unpowered_repeater", state: "minecraft:cardinal_direction" }
        ];

    }

    getFrontandBack(direction, block) {
        let frontBlock, backBlock, leftBlock, rightBlock;
        switch (direction) {
            case 'north':
                frontBlock = block.north();
                backBlock = block.south();
                rightBlock = block.east();
                leftBlock = block.west();
                break;
            case 'south':
                frontBlock = block.south();
                backBlock = block.north();
                rightBlock = block.west();
                leftBlock = block.east();
                break;
            case 'east':
                frontBlock = block.east();
                backBlock = block.west();
                rightBlock = block.south();
                leftBlock = block.north();
                break;
            case 'west':
                frontBlock = block.west();
                backBlock = block.east();
                rightBlock = block.north();
                leftBlock = block.south();
                break;
        }
        return { frontBlock, backBlock, leftBlock, rightBlock };
    }
    getCounterData() {
        return JSON.parse(world.getDynamicProperty(this.DYNAMIC_PROPERTY_NAME) || "[]");
    }

    setCounterData(data) {
        world.setDynamicProperty(this.DYNAMIC_PROPERTY_NAME, JSON.stringify(data));
    }

    updateCounterData(block) {
        const locationStr = `${block.location.x},${block.location.y},${block.location.z}`;
        let data = this.getCounterData();
        let counter = data.find(counter => counter.loc === locationStr);

        if (!counter) {
            counter = { loc: locationStr, tickDelay: 1 };
            data.push(counter);
        }

        this.setCounterData(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") {
            const AllStates = [
                { state: "minecraft:cardinal_direction", values: ["north", "east", "south", "west"] },
                { state: "minecraft:facing_direction", values: ["north", "east", "south", "west", "up", "down"] }
            ]

            AllStates.some((stateObj) => {
                const currentState = block.permutation.getState(stateObj.state);

                if (currentState !== undefined && currentState !== null) {
                    const stateValues = stateObj.values;
                    const currentStateIndex = stateValues.indexOf(currentState);
                    const nextState = currentStateIndex >= stateValues.length - 1 ? stateValues[0] : stateValues[currentStateIndex + 1];

                    block.setPermutation(block.permutation.withState(stateObj.state, nextState));
                    block.dimension.runCommand(`playsound vr.stutterturn @a ${block.location.x} ${block.location.y} ${block.location.z}`)
                }
            });
            return;
        }

        this.updateCounterData(block)

        const locationStr = `${block.location.x},${block.location.y},${block.location.z}`;
        let data = this.getCounterData();
        let counter = data.find(counter => counter.loc === locationStr);
        block.dimension.runCommand(`playsound random.click @a ${block.location.x} ${block.location.y} ${block.location.z}`)
        let timeMesure = block.permutation.getState('pb_red:time_mesure');
        const CustomRepeaterGUI = new ModalFormData()
        CustomRepeaterGUI.title("Custom Repeater")
        CustomRepeaterGUI.toggle("In Seconds / In ticks", timeMesure)
        CustomRepeaterGUI.slider("Delay", 1, 60, 1, counter.tickDelay ? (timeMesure ? counter.tickDelay : counter.tickDelay / 20) : 10)
        CustomRepeaterGUI.show(player).then((selec) => {
            if (selec.canceled) {
                return;
            }
            if (selec.formValues[0]) {
                block.setPermutation(block.permutation.withState('pb_red:time_mesure', true));
                counter.tickDelay = selec.formValues[1];
                let delayDisplay = this.convertTicksToTimeString(counter.tickDelay)
                player.runCommand(`tellraw @s {"rawtext":[{"text":"Set a delay of ${delayDisplay}"}]}`)
            }
            else {
                counter.tickDelay = selec.formValues[1] * 20;
                block.setPermutation(block.permutation.withState('pb_red:time_mesure', false));
                let delayDisplay = this.convertTicksToTimeString(counter.tickDelay)
                player.runCommand(`tellraw @s {"rawtext":[{"text":"Set a delay of ${delayDisplay}"}]}`)
            }

            this.setCounterData(data);
        });
    }
    convertTicksToTimeString(ticks) {
        const seconds = (ticks / 20).toFixed(2);
        return `§e${seconds} seconds`;
    }
    removeDynamicProperties(block) {
        const locationStr = `${block.location.x},${block.location.y},${block.location.z}`;
        let data = this.getCounterData();
        data = data.filter(counter => counter.loc !== locationStr);
        this.setCounterData(data);
    }

    onTick(e) {
        const { block } = e;
        let direction = block.permutation.getState('minecraft:cardinal_direction');
        const { frontBlock, backBlock, leftBlock, rightBlock } = this.getFrontandBack(direction, block);
        const directionList = ["north", "east", "south", "west"];
        let hasRedstonePower = false;
        if (!backBlock) return
        const redstoneBlock = this.REDSTONE_POWER_BLOCKS.find(({ id }) => backBlock.permutation.matches(id));
        if (!redstoneBlock) {
            block.setPermutation(block.permutation.withState('pb_red:powered_in', false));
            block.setPermutation(block.permutation.withState('pb_red:powered_out', false));
            return false;
        }
        const { id, state } = redstoneBlock;
        if (id === "minecraft:redstone_wire") {
            let redstonePowerState = backBlock.permutation.getState(state);
            if (redstonePowerState > 0)
                hasRedstonePower = true;
        } else {
            if (id === "minecraft:powered_repeater") {
                if (backBlock.permutation.getState(state) === directionList[(directionList.indexOf(direction) - 2 + directionList.length) % directionList.length])
                    hasRedstonePower = true;
            }
        }


        const previousState = block.permutation.getState('pb_red:powered_in') == true;

        if (hasRedstonePower) {
            const locationStr = `${block.location.x},${block.location.y},${block.location.z}`;
            let data = this.getCounterData();
            let counter = data.find(counter => counter.loc === locationStr);
            if (!counter) return
            block.setPermutation(block.permutation.withState('pb_red:powered_in', true));
            system.runTimeout(() => {
                const locationStr2 = `${block.location.x},${block.location.y},${block.location.z}`;
                let data2 = this.getCounterData();
                let counter2 = data2.find(counter2 => counter2.loc === locationStr2);
                if (!frontBlock || !e.block) return
                try {

                    if (frontBlock.permutation.matches("minecraft:unpowered_repeater") && counter2?.tickDelay == counter?.tickDelay && e.block && frontBlock.permutation.getState("minecraft:cardinal_direction") === directionList[(directionList.indexOf(direction) - 2 + directionList.length) % directionList.length]) {
                        frontBlock.setPermutation(BlockPermutation.resolve("minecraft:powered_repeater", { 'minecraft:cardinal_direction': directionList[(directionList.indexOf(direction) - 2 + directionList.length) % directionList.length] }));
                        block.setPermutation(block.permutation.withState('pb_red:powered_out', true));

                    }
                } catch {
                    // console.warn("Unloaded chunk error (custom repeater)")
                }


            }, counter.tickDelay)

        } else if ((!hasRedstonePower)) {
            this.updateCounterData(block)
            const locationStr = `${block.location.x},${block.location.y},${block.location.z}`;
            let data = this.getCounterData();
            let counter = data.find(counter => counter.loc === locationStr);
            block.setPermutation(block.permutation.withState('pb_red:powered_in', false));
            system.runTimeout(() => {
                try {
                    block.setPermutation(block.permutation.withState('pb_red:powered_out', false));

                } catch { }
            }, counter.tickDelay > 10 ? counter.tickDelay - 10 : 10)
        }
    }
}