import { Dimension, Entity } from "@minecraft/server";
import { Vec3 } from "./Vec3";
export const notBreakableBlocks = [
    "minecraft:air",
    "minecraft:bedrock",
    "minecraft:chest",
    "minecraft:end_portal_frame",
    "minecraft:monster_spawner",
    "minecraft:command_block",
    "minecraft:chain_command_block",
    "minecraft:repeating_command_block",
    "minecraft:obsidian",
    "minecraft:trapped_chest",
    "minecraft:barrier",
    "minecraft:portal",
    "minecraft:end_portal",
    "minecraft:water",
    "minecraft:flowing_water",
    "minecraft:lava",
    "minecraft:flowing_lava"
]
/**
 * 
 * @param {Number} min 
 * @param {Number} max 
 * @returns {Number}
 */
export function getRandomQuantity(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
};
/**
 * 
 * @param {Number} min 
 * @param {Number} max 
 * @returns {Number}
 */
export function getRandomQuantityFloat(min, max) {
    return Math.random() * (max - min) + min;
};
/**
 * 
 * @param {Array} lootTable 
 */
export function getRandomLoot(lootTable) {
    const totalWeight = lootTable.reduce((sum, loot) => sum + loot.weight, 0);
    const random = Math.random() * totalWeight;

    let accumulatedWeight = 0;
    for (let i = 0; i < lootTable.length; i++) {
        const loot = lootTable[i];
        accumulatedWeight += loot.weight;
        if (random <= accumulatedWeight) {
            if (loot.type === "item") {
                return { type: loot.type, value: loot.value, quantity: loot.quantity, index: i };
            } else if (loot.type === "action") {
                const actionName = loot.actionName;
                return { type: loot.type, value: actionName, index: i };
            }
        }
    }
};
/**
 * 
 * @param {Array} lootTable 
 * @param {Number} min 
 * @param {Number} max 
 */
export function getMultipleLoot(lootTable, min, max) {
    const numLoots = getRandomQuantity(min, max);
    const lootResults = [];

    for (let i = 0; i < numLoots; i++) {
        lootResults.push(getRandomLoot(lootTable));
    }

    return lootResults;
};
/**
 * 
 * @param {Array} array 
 */
export function randomIndex(array) {
    return Math.floor(Math.random() * array.length);
};
/**
 * 
 * @param {Entity} entity 
 */
export function localCoordsVars(entity) {
    if (entity.isValid() == true) {
        const zVec = entity?.getViewDirection();
        const xVec = Vec3(zVec.z, 0, -zVec.x).normalized;
        const yVec = Vec3.cross(zVec, xVec).normalized;

        return {
            xVec: xVec,
            yVec: yVec,
            zVec: zVec
        }
    } else return;
};
/**
 * 
 * @param {Entity} entity 
 * @param {Entity} sourceEntity 
 * @returns 
 */
export function lookAtEntity(entity, sourceEntity) {
    const rot = sourceEntity?.getRotation();

    const dx = entity.location.x - sourceEntity.location.x;
    const dy = entity.location.y - sourceEntity.location.y;
    const dz = entity.location.z - sourceEntity.location.z;

    let yaw = Math.atan2(dz, dx) * (180 / Math.PI) - 90 - rot.y;
    yaw = (yaw + 360) % 360;

    if (yaw > 180) {
        yaw -= 360;
    }

    if (yaw > 135) {
        yaw = 135;
    } else if (yaw < -135) {
        yaw = -135;
    }

    const distanceXZ = Math.sqrt(dx * dx + dz * dz);
    let pitch = Math.atan2(dy, distanceXZ) * (180 / Math.PI);

    return {pitch: pitch, yaw: yaw};
};
/**
 * 
 * @param {Vec3} center 
 * @param {Number} radius 
 * @param {Dimension} dimension 
 * @returns 
 */
export async function GetRedstoneInRadius(center, radius, dimension) {
    const ids = [
        "minecraft:redstone_block",
        "minecraft:redstone_wire",
        "minecraft:lever",
        "minecraft:redstone_torch",
        "minecraft:powered_repeater",
        "minecraft:powered_comparator"
    ];
    const allowedStates = [
        "redstone_signal",
        "open_bit",
        "button_pressed_bit",
        "powered_bit"
    ];
    function intState(state, blockAtLocation) {
        if (state !== undefined && state == 0) {
            blockStateFound = true;
        } else if (state !== undefined && state > 0) {
            blockStateFound = true;
            blockFound = blockAtLocation;
        }
    };
    function boolState(state, blockAtLocation) {
        if (state !== undefined && state === false) {
            blockStateFound = true;
        } else if (state !== undefined && state === true) {
            blockStateFound = true;
            blockFound = blockAtLocation;
        }
    };

    let blockFound = null;
    let blockStateFound = false;

    // List of relative positions forming a cross shape
    const directions = [
        { x: 0, y: 0, z: 1 },  // Forward
        { x: 0, y: 0, z: -1 }, // Backward
        { x: 1, y: 0, z: 0 },  // Right
        { x: -1, y: 0, z: 0 }, // Left
        { x: 0, y: 1, z: 0 },  // Up
        { x: 0, y: -1, z: 0 }  // Down
    ];

    for (let d of directions) {
        for (let i = 1; i <= radius; i++) {
            const location = {
                x: center.x + d.x * i,
                y: center.y + d.y * i,
                z: center.z + d.z * i
            };

            let blockAtLocation;
            try {
                blockAtLocation = dimension.getBlock(location);
            } catch { }

            if (blockAtLocation !== undefined) {
                ids.forEach((id) => {
                    if (blockAtLocation?.permutation.matches(id)) {
                        allowedStates.forEach((allowedState) => {
                            const state = blockAtLocation?.permutation.getState(allowedState);
                            if (allowedState === `redstone_signal`) {
                                intState(state, blockAtLocation);
                            };
                            if (allowedState === `open_bit`) {
                                boolState(state, blockAtLocation);
                            };
                            if (allowedState === `button_pressed_bit`) {
                                boolState(state, blockAtLocation);
                            };
                            if (allowedState === `powered_bit`) {
                                boolState(state, blockAtLocation);
                            }
                        });
                        if (blockStateFound === false) {
                            blockFound = blockAtLocation;
                        }
                    }
                });
            }
        }
    }

    return blockFound;
};