import {system, world} from "@minecraft/server"
import {ballista} from "cubc/ra_su/util/ballista"

let prev_raft_coords = [];
let prev_light_coords = [];

system.runInterval(() => {
    ballista();
}, 1);

function detect_land(raft, check_coords) {
    const overworld = world.getDimension('overworld');
    let {x: ox, y: oy, z: oz} = raft.location;

    raft.runCommand('tag @e remove cubc_ra_su_self');
    raft.runCommand('tag @s add cubc_ra_su_self');
    raft.runCommand('tag @s remove cubc_ra_su_raft_close');

    let radius = 5;
    if (raft.typeId === "cubc_ra_su:raft_1") {
        radius = 5;
    }
    if (raft.typeId === "cubc_ra_su:raft_2") {
        radius = 6;
    }
    if (raft.typeId === "cubc_ra_su:raft_3") {
        radius = 7;
    }
    if (raft.typeId === "cubc_ra_su:raft_4") {
        radius = 8
    }

    raft.runCommand(`execute positioned ${ox} ${oy} ${oz} if entity @e[r=${radius}, family=raft, tag=!cubc_ra_su_self] run tag @s add cubc_ra_su_raft_close`)
    if (raft.getTags().includes('cubc_ra_su_raft_close')) {
        raft.runCommand('scriptevent cubc_ra_su:tp_back');
        return
    }

    for (const coord of check_coords) {

        const {x: x, y: y, z: z} = coord;
        const block = overworld.getBlock({x: x, y: y - 1, z: z}).permutation;

        if (
            block.matches("minecraft:sand") ||
            block.matches("minecraft:stone") ||
            block.matches("minecraft:dirt") ||
            block.matches("minecraft:grass") ||
            block.matches("minecraft:grass_block") ||
            block.matches("minecraft:clay")
        ) {
            raft.runCommand('scriptevent cubc_ra_su:tp_back');
            return;
        }
    }

    raft.runCommand('scriptevent cubc_ra_su:register_location');
}

export function update_raft() {
    const overworld = world.getDimension('overworld');
    const raft_entities = overworld.getEntities({
        families: ["raft"],
        tags: ["cubc_ra_su_player_close"]
    });

    const light_entities = overworld.getEntities({
        families: ["light"]
    });

    let new_raft_coords = [];
    let new_light_coords = [];

    for (const raft of raft_entities) {

        let {x: ox, y: oy, z: oz} = raft.location;
        ox = Math.round(ox, 2) - 0.5;
        oy = Math.round(oy, 2);
        oz = Math.round(oz, 2) - 0.5;

        const angle = raft.getRotation();
        const facingX = Math.cos((angle.y + 90) * (Math.PI / 180));
        const facingZ = Math.sin((angle.y + 90) * (Math.PI / 180));

        let r_width = 0;
        let r_length = 0;
        let raft_level = parseInt(raft.typeId.slice(-1));

        let db = 0.5

        if (raft_level === 0) {
            r_width = 0.75;
            r_length = 1.25;
            db = 0.25
        }
        if (raft_level === 1) {
            r_width = 1.25;
            r_length = 1.75;
            db = 0.25
        }
        if (raft_level === 2) {
            r_width = 1.5;
            r_length = 3;
        }
        if (raft_level === 3) {
            r_width = 1.5;
            r_length = 4.5;
        }
        if (raft_level === 4) {
            r_width = 3;
            r_length = 6;
        }
        const check_coords = []

        for (let dx = -r_width; dx < r_width + db; dx += db) {
            for (let dz = -r_length; dz < r_length + db; dz += db) {

                if (dz >= 0 && Math.abs(dx) >= 2) {
                    continue;
                } else {
                    const x = Math.round(ox + facingX * dz - facingZ * dx, 1);
                    const y = oy;
                    const z = Math.round(oz + facingZ * dz + facingX * dx, 1);

                    if (raft.getTags().includes('cubc_ra_su_should_barrier')) {
                        new_raft_coords.push({x: x, y: y, z: z});
                    }

                    check_coords.push({x: x, y: y, z: z})
                }
            }
        }

        detect_land(raft, check_coords)
    }

    for (const light of light_entities) {
        let {x: lx, y: ly, z: lz} = light.location;
        lx = Math.round(lx, 2);
        ly = Math.round(ly, 2);
        lz = Math.round(lz, 2);
        for (const dx of [-1, 0, 1]) {
            for (const dz of [-1, 0, 1]) {
                for (const dy of [-1, 0, 1]) {
                    const x = lx + dx;
                    const y = ly + dy;
                    const z = lz + dz;
                    new_light_coords.push({x: x, y: y, z: z});
                }
            }
        }
    }

    // Set to water
    // Set to barrier
    for (const coord of new_raft_coords) {
        let {x: x, y: y, z: z} = coord;
        overworld.runCommand(`execute positioned ${x} ${y} ${z} if block ~~-1~ water run setblock ~~-1~ barrier`);
        overworld.runCommand(`execute positioned ${x} ${y} ${z} if block ~~-1~ kelp run setblock ~~-1~ barrier`);
    }

    for (const coord of prev_raft_coords) {
        if (!new_raft_coords.some(newCoord => newCoord.x === coord.x && newCoord.y === coord.y && newCoord.z === coord.z)) {
            overworld.runCommand(`execute positioned ${coord.x} ${coord.y} ${coord.z} if block ~~-1~ barrier run setblock ~~-1~ water`);
        }
    }

    // Set light_block
    for (const coord of new_light_coords) {
        let {x: x, y: y, z: z} = coord;
        overworld.runCommand(`execute positioned ${x} ${y} ${z} if block ~~~ air run setblock ~~~ light_block ["block_light_level"= 15]`);
    }

    for (const coord of prev_light_coords) {
        if (!new_light_coords.some(newCoord => newCoord.x === coord.x && newCoord.y === coord.y && newCoord.z === coord.z)) {
            overworld.runCommand(`execute positioned ${coord.x} ${coord.y} ${coord.z} if block ~~~ light_block ["block_light_level"= 15] run setblock ~~~ air`);
        }
    }

    prev_raft_coords = new_raft_coords;
    prev_light_coords = new_light_coords;
}

system.runInterval(() => {
    update_raft();
}, 10);
