import { showArea } from './particle_area_marker.js'
import { world, MolangVariableMap, system } from "@minecraft/server"


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

        this.MINECRAFT_ORES = {
            coal: [
                "minecraft:coal_ore",
                "minecraft:deepslate_coal_ore"
            ],
            iron: [
                "minecraft:iron_ore",
                "minecraft:deepslate_iron_ore"
            ],
            copper: [
                "minecraft:copper_ore",
                "minecraft:deepslate_copper_ore"
            ],
            gold: [
                "minecraft:gold_ore",
                "minecraft:deepslate_gold_ore"
            ],
            redstone: [
                "minecraft:redstone_ore",
                "minecraft:lit_redstone_ore",
                "minecraft:deepslate_redstone_ore",
                "minecraft:lit_deepslate_redstone_ore"
            ],
            emerald: [
                "minecraft:emerald_ore",
                "minecraft:deepslate_emerald_ore"
            ],
            lapis: [
                "minecraft:lapis_ore",
                "minecraft:deepslate_lapis_ore"
            ],
            diamond: [
                "minecraft:diamond_ore",
                "minecraft:deepslate_diamond_ore"
            ],
            nether_gold: [
                "minecraft:nether_gold_ore"
            ],
            quartz: [
                "minecraft:quartz_ore"
            ],
            ancient_debris: [
                "minecraft:ancient_debris"
            ]
        };

        this.MINECRAFT_ORES_LOOT = [
            "minecraft:coal",
            "minecraft:iron_ingot",
            "minecraft:copper_ingot",
            "minecraft:gold_ingot",
            "minecraft:redstone",
            "minecraft:emerald",
            "minecraft:lapis_lazuli",
            "minecraft:diamond",
            "minecraft:gold_nugget",
            "minecraft:quartz",
            "minecraft:ancient_debris"
        ];
        this.MINECRAFT_ORES_KEYS = [
            'coal',
            'iron',
            'copper',
            'gold',
            'redstone',
            'emerald',
            'lapis',
            'diamond',
            'nether_gold',
            'quartz',
            'ancient_debris'
        ];

        this.ARROW_COLOR = [
            { r: 0, g: 1, b: 0 },
            { r: 0.7, g: 0.7, b: 0 },
            { r: 1, g: 0.5, b: 0 },
            { r: 1, g: 0, b: 0 },
        ];

    }

    onPlayerInteract(e) {
        const block = e.block;
        const player = e.player;
        const blockCenter = {
            x: block.location.x + 0.5,
            y: block.location.y + 0.5,
            z: block.location.z + 0.5
        }

        let selectedSlot = player.selectedSlotIndex;
        let handItem = player.getComponent("inventory").container.getItem(selectedSlot);

        if (this.MINECRAFT_ORES_LOOT.includes(handItem?.typeId)) {
            block.setPermutation(block.permutation.withState('pb_red:ore_index', this.MINECRAFT_ORES_LOOT.indexOf(handItem.typeId) + 1))
            player.runCommand(`tellraw @s {"rawtext":[{"text":"Now Detecting §e${this.MINECRAFT_ORES_KEYS[this.MINECRAFT_ORES_LOOT.indexOf(handItem.typeId)]}§r in the area!"}]}`)
            player.runCommand(`clear @s ${handItem.typeId} 0 1`);
            block.dimension.runCommand(`playsound random.click @a ${block.location.x} ${block.location.y} ${block.location.z}`)

        }
        if (handItem.typeId == "pb_red:redstone_wrench") {
            block.setPermutation(block.permutation.withState('pb_red:particle', !block.permutation.getState("pb_red:particle")))
            block.dimension.runCommand(`playsound random.click @a ${block.location.x} ${block.location.y} ${block.location.z}`)

        }

    }

    onTick(e) {
        const { block } = e;
        const blockCenter = {
            x: block.location.x + 0.5,
            y: block.location.y + 0.5,
            z: block.location.z + 0.5
        }
        if (!this.isOreDetectorBlock(block)) return

        const nearbyPlayers = block.dimension.getEntities({ type: 'minecraft:player', location: block.location, maxDistance: 15 })
        if (nearbyPlayers.length == 0) return
        const oreIndex = block.permutation.getState('pb_red:ore_index')

        const showParticle = block.permutation.getState("pb_red:particle")
        if (showParticle) {
            try {
                showArea(blockCenter, block.dimension, 1.5, 10)
            } catch { }
        }

        if (oreIndex == 0) return
        const oreKey = this.MINECRAFT_ORES_KEYS[oreIndex - 1];
        const oreToSearch = this.MINECRAFT_ORES[oreKey];
        const oreBlocks = this.getOresBlocks(blockCenter, 10, oreToSearch, block)


        if (oreBlocks.length > 0) {
            //spawn Green "V" particle on top of the detector
            oreBlocks.forEach((loc) => {
                const unitVector = this.getUnitVector(blockCenter, loc)

                this.createParticleLine(blockCenter, { x: loc.x - unitVector.x, y: loc.y - unitVector.y, z: loc.z - unitVector.z }, block, 5, unitVector, blockCenter)
            })
        } else {
            //spawn Red "X" particle on top of the detector
        }


    }

    createParticleLine(startPos, endPos, block, particleCount, unitVector, blockCenter) {

        const distanceX = endPos.x - startPos.x;
        const distanceY = endPos.y - startPos.y;
        const distanceZ = endPos.z - startPos.z;

        const stepX = distanceX / particleCount;
        const stepY = distanceY / particleCount;
        const stepZ = distanceZ / particleCount;

        for (let i = 0; i <= particleCount; i++) {
            const particleX = startPos.x + (stepX * i);
            const particleY = startPos.y + (stepY * i);
            const particleZ = startPos.z + (stepZ * i);

            const particleLoc = { x: particleX + unitVector.x, y: particleY + unitVector.y, z: particleZ + unitVector.z }
            const color = this.ARROW_COLOR[this.getDistanceCategory(endPos, particleLoc)]

            system.runTimeout(() => {
                spawnOreRadarParticle(
                    particleLoc,
                    block.dimension, 0.5, 0.2, unitVector, color
                )
            }, i * 2)

        }
    }

    getOresBlocks(center, radius, ores, detector) {
        let blocks = [];
        for (let x = -radius; x <= radius; x++) {
            for (let y = -radius; y <= radius; y++) {
                for (let z = -radius; z <= radius; z++) {
                    if (x * x + y * y + z * z <= radius * radius) {
                        let blockLocation = { x: center.x + x, y: center.y + y, z: center.z + z };
                        try {
                            const oreBlock = detector.dimension.getBlock(blockLocation)
                            if (ores.includes(oreBlock.typeId)) {
                                blocks.push(blockLocation);
                            }
                        } catch { }

                    }
                }
            }
        }
        return blocks;
    }

    getDistanceCategory(pos1, pos2) {
        const dx = pos2.x - pos1.x;
        const dy = pos2.y - pos1.y;
        const dz = pos2.z - pos1.z;

        const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
        const roundedDistance = Math.round(distance);

        if (roundedDistance < 2.5) {
            return 0;
        } else if (roundedDistance <= 3.5) {
            return 1;
        } else if (roundedDistance <= 6) {
            return 2;
        } else if (roundedDistance <= 11) {
            return 3;
        }

        return 3;
    }

    getUnitVector(pos1, pos2) {
        const vector = {
            x: pos2.x - pos1.x,
            y: pos2.y - pos1.y,
            z: pos2.z - pos1.z
        };

        const magnitude = Math.sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z);

        if (magnitude === 0) {
            return { x: 0, y: 0, z: 0 };
        }

        const unitVector = {
            x: vector.x / magnitude,
            y: vector.y / magnitude,
            z: vector.z / magnitude
        };

        return unitVector;
    }


    isOreDetectorBlock(block) {
        return block.typeId === "pb_red:redstone_ore_detector";
    }
}




function spawnOreRadarParticle(location, dimension, duration, size, dirVec, color) {

    let mvm = new MolangVariableMap();
    mvm.setVector3(`variable.dir`, dirVec)
    mvm.setFloat(`variable.duration`, duration);
    mvm.setFloat(`variable.size`, size);
    mvm.setColorRGB(`variable.color`, { red: color.r, green: color.g, blue: color.b })
    try {
        world.getDimension(dimension.id).spawnParticle('pb_red:ore_detector_arrow', { x: location.x, y: location.y, z: location.z }, mvm);
    } catch {
        // console.error("Can't spawn Particle In unloaded Chunks")
    }
}


// world.afterEvents.itemUse.subscribe((e) => {
//     if (e.itemStack.typeId == "minecraft:clock") {
//         spawnOreRadarParticle(e.source.location, e.source.dimension, 5, 1, { x: 1, y: 1, z: 1 }, { r: 0.5, g: 1, b: 0 })
//     }

// })