import {
    world,
    system,
    BlockVolume
} from "@minecraft/server";

function getTransporters(dim, loc, og) {
    const transportersFound = []
    var corner1 = { x: loc.x - 16, y: loc.y + 8, z: loc.z - 16 }
    var corner2 = { x: loc.x + 16, y: loc.y - 8, z: loc.z + 16 }
    var volume = dim.getBlocks((new BlockVolume(corner1, corner2)), {})
    for (const blockLoc of volume.getBlockLocationIterator()) {
        let block = dim.getBlock(blockLoc)
        if (block.typeId === "mm:unobtanium_transporter") {
            const perm = block.permutation
            const power = perm.getState("mm:charge")
            if (power == 4 && block.above().isAir) {
                transportersFound.push(block)
            }
        }
    }
    return transportersFound;
}

function findNearest(list, loc) {
    var closestBlock = undefined
    var closestDist = 26
    for (const block of list) {
        const dist = Math.hypot(loc.x - block.x, loc.y - block.y, loc.z - block.z)
        if (dist < closestDist && dist > 0) {
            closestDist = dist
            closestBlock = block
        }
    }
    return closestBlock
}

function transport(block) {
    if (block.above().isAir == false) return false;
    const dim = block.dimension
    const loc = block.location


    const targets = dim.getEntitiesAtBlockLocation(block.above())
    if (targets.length == 0) return false;
    const nearbyTransporters = getTransporters(dim, loc, block)
    if (nearbyTransporters.length == 0) return false;
    const nearest = findNearest(nearbyTransporters, loc)
    if (nearest == undefined) return false;
    for (const target of targets) {
        target.tryTeleport(nearest.above().bottomCenter())
    }
    var particleLoc = nearest.above().bottomCenter()
    particleLoc.y = particleLoc.y + 0.1
    dim.spawnParticle("mm:unobtanium_transporter_recieve", particleLoc)
    const perm = block.permutation
    var newPerm = perm.withState("mm:charge", 2);
    block.setPermutation(newPerm)
    const nearPerm = nearest.permutation
    var newNearPerm = nearPerm.withState("mm:charge", 0);
    nearest.setPermutation(newNearPerm)
    return true;
}

system.beforeEvents.startup.subscribe((event) => {
    event.blockComponentRegistry.registerCustomComponent("mm:unobtanium_transporter", {
        onRedstoneUpdate(e) {
            const block = e.block;
            const loc = block.location;
            const dim = e.dimension;
            const newPower = e.powerLevel;
            const perm = block.permutation
            if (newPower == 0) {
                var newPerm = perm.withState("mm:powered", false);
                block.setPermutation(newPerm)
                return;
            }
            const powered = perm.getState("mm:powered")
            const chargeLevel = perm.getState("mm:charge")
            if (powered == false && chargeLevel == 4) {
                var newPerm = perm.withState("mm:powered", true);
                block.setPermutation(newPerm)
                const tryTeleport = transport(block)
                var particleLoc = block.above().bottomCenter()
                particleLoc.y = particleLoc.y + 0.1
                dim.spawnParticle("mm:unobtanium_transporter_send", particleLoc)
                if (tryTeleport == true) {
                    dim.spawnParticle("mm:unobtanium_transporter", particleLoc)
                    dim.playSound("block.transporter.teleport", block.location)
                } else {
                    dim.playSound("block.transporter.fail", block.location, { volume: 0.66 })

                }
                system.runTimeout(() => {
                    if (dim.isChunkLoaded(loc) == false) return;
                    if (dim.getBlock(loc) !== undefined && dim.getBlock(loc).typeId !== "mm:unobtanium_transporter") return;
                    newPerm = block.permutation.withState("mm:powered", false);
                    block.setPermutation(newPerm)

                }, 10)
            }
        },
        onTick(e) {
            const block = e.block;
            const perm = block.permutation
            const dim = block.dimension
            const powered = perm.getState("mm:powered")
            const chargeLevel = perm.getState("mm:charge")
            if (powered == false && chargeLevel < 4) {
                var newPerm = perm.withState("mm:charge", chargeLevel + 1);
                dim.playSound("block.transporter.charge" + `${(chargeLevel + 1)}`, block.location, { volume: 0.5 })
                block.setPermutation(newPerm)
            }
        }
    })
})