import {system, world} from "@minecraft/server"
import "cubc/ra_su/util/block_place_system";
import "cubc/ra_su/util/shark";
import "cubc/ra_su/util/health";
import "cubc/ra_su/util/projectiles";
import {update_raft} from "cubc/ra_su/util/block_place_system"
import "cubc/ra_su/weapons";

function get_integer(str) {
    return parseInt(str.replace(/\D/g, ""));
}

function projectile_hit(source_entity) {
    try {
        if (source_entity.typeId === "cubc_ra_su:ballista_arrow") {
            source_entity.runCommand(`event entity @s cubc_ra_su:despawn`)
        }
    } catch {
    }
}

world.afterEvents.itemUse.subscribe(eventData => {
    const item = eventData.itemStack
    const player = eventData.source
    const type_id = item.typeId;

    if (type_id.includes('cubc_ra_su:')) {
        if (type_id.includes('book')) {
            player.runCommand(`execute if entity @s[scores={cubc_ra_su_item_cooldown=0}] run function cubc/ra_su/book/previous_page`);
            player.runCommand(`scoreboard players set @s[scores={cubc_ra_su_item_cooldown=0}] cubc_ra_su_item_cooldown 10`);
        }
        if (type_id.includes('totem')) {
            player.runCommand(`execute if entity @s[scores={cubc_ra_su_item_cooldown=0}] run function cubc/ra_su/pb/use_totem`);
            player.runCommand(`scoreboard players set @s[scores={cubc_ra_su_item_cooldown=0}] cubc_ra_su_item_cooldown 10`);
        }
    }
})


world.afterEvents.projectileHitBlock.subscribe((eventData) => {
    if (!eventData.getBlockHit().block.permutation.matches('minecraft:water'))
        projectile_hit(eventData.projectile)
});

world.afterEvents.projectileHitEntity.subscribe((eventData) => {
    projectile_hit(eventData.projectile)
});

function getRandomPointOnCircle(minRadius, maxRadius) {
    // Generate a random angle in radians
    const angle = Math.random() * 2 * Math.PI;

    // Generate a random radius between minRadius and maxRadius
    const radius = minRadius + Math.random() * (maxRadius - minRadius);

    // Calculate the x and y coordinates
    const x = radius * Math.cos(angle);
    const z = radius * Math.sin(angle);

    return {x, z};
}

function getScore(entity, scoreboard) {
    try {
        const score = world.scoreboard.getObjective(scoreboard).getScore(entity)
        if (score === undefined) {
            return 0;
        } else {
            return score;
        }
    } catch {
    }
    // console.warn(`scoreboard ${scoreboard} not found on ${entity.nameTag}`);
    return 0;
}

world.afterEvents.entityHitEntity.subscribe((event) => {
    const damager = event.damagingEntity;

    try {
        damager.runCommand(`tag @e remove cubc_ra_su_damager`);
        damager.runCommand(`tag @s add cubc_ra_su_damager`);

        event.hitEntity.runCommand(`tag @e remove cubc_ra_su_hit`);
        event.hitEntity.runCommand(`tag @s add cubc_ra_su_hit`);

        if (event.hitEntity.typeId.includes("shark") && !event.hitEntity.typeId.includes("shark_seat")) {
            event.hitEntity.runCommand("ride @s stop_riding");
            event.hitEntity.runCommand("scoreboard players set @s cubc_ra_su:dismount_timer 120");
        }

        // Harpoon hits a shark
        damager.runCommand(`execute as @s[type=player, hasitem={item=cubc_ra_su:harpoon, location=slot.weapon.mainhand}] run execute as @e[tag=cubc_ra_su_hit, type=cubc_ra_su:skeleton_shark] at @s run damage @s 10 magic`);
        damager.runCommand(`execute as @s[type=player, hasitem={item=cubc_ra_su:harpoon, location=slot.weapon.mainhand}] run execute as @e[tag=cubc_ra_su_hit, type=cubc_ra_su:skeleton_shark] at @s run particle minecraft:critical_hit_emitter`);
        damager.runCommand(`execute as @s[type=player, hasitem={item=cubc_ra_su:harpoon, location=slot.weapon.mainhand}] run execute as @e[tag=cubc_ra_su_hit, type=cubc_ra_su:tiger_shark] at @s run damage @s 10 magic`);
        damager.runCommand(`execute as @s[type=player, hasitem={item=cubc_ra_su:harpoon, location=slot.weapon.mainhand}] run execute as @e[tag=cubc_ra_su_hit, type=cubc_ra_su:tiger_shark] at @s run particle minecraft:critical_hit_emitter`);
    } catch {

    }
})

function getRandomInt(max) {
    return Math.floor(Math.random() * max);
}

system.afterEvents.scriptEventReceive.subscribe((event) => {
    const {id, message, sourceEntity, sourceType} = event;
    let {x: ox, y: oy, z: oz} = sourceEntity.location;
    ox = Math.round(ox, 0);
    oy = Math.round(oy, 0);
    oz = Math.round(oz, 0);
    let dimension = event.sourceEntity.dimension;

    if (id === "cubc_ra_su:delay") {
        let delay = parseInt(message.split('/')[0], 10);
        let command = message.split('/').slice(1).join('/');

        system.runTimeout(() => {
            try {
                sourceEntity.runCommand(command);
            } catch {

            }
        }, delay);
    }

    if (id === "cubc_ra_su:place_boat") {
        system.runTimeout(() => {
            dimension.runCommand(`execute as @r at @s positioned ${ox} ${oy} ${oz} run execute as @a[r=30] at @s run playsound cubc_ra_su.scare @s ~~~ 0.5`);
            dimension.runCommand(`execute as @r at @s positioned ${ox} ${oy} ${oz} run particle cubc_ra_su:smoke_boat_${message}`);
            dimension.runCommand(`execute as @r at @s positioned ${ox} ${oy} ${oz} run function cubc/ra_su/pb/boat/boat_${message}_def`);
            for (let i = 0; i < 5; i++) {
                const x = Math.round(ox + (Math.random() * 4 - 2));
                const z = Math.round(oz + (Math.random() * 10 - 5));
                dimension.runCommand(`execute positioned ${x} ${oy - 8} ${z} if block ~~~ water run summon cubc_ra_su:skeleton_shark`);
            }
        }, 60);
    }

    if (id === "cubc_ra_su:repeat") {
        let data = message.split('/')[0];
        let command = message.split('/').slice(1).join('/');

        let repeat = get_integer(data.split(',')[0]);
        let delay = get_integer(data.split(',')[1]);

        for (let i = 0; i < repeat; i++) {
            try {
                system.runTimeout(() => {
                    sourceEntity.runCommand(command);
                }, i * delay);
            } catch {}
        }
    }

    if (id === "cubc_ra_su:spawn_trash") {
        const {x: dx, z: dz} = getRandomPointOnCircle(20, 60);
        const dys = [1, 0, -1, -2, -3, -4, -5, -6, -7];
        for (const dy of dys) {
            try {
                const block = sourceEntity.dimension.getBlock({x: ox + dx, y: oy + dy, z: oz + dz});
                if (block.permutation.matches('minecraft:water')) {
                    sourceEntity.runCommand(`execute positioned ${ox + dx} ${oy + dy + 1} ${oz + dz} unless entity @e[type=cubc_ra_su:${message}, r=30] run summon cubc_ra_su:${message} ~~~`);
                    break;
                }
            } catch {
            }
        }
    }

    // Give back items when killing a creator
    if (id === "cubc_ra_su:kill_creator") {
        let items = [
            'stick',
            'string',
            'bone',
            'iron_ingot',
            'flint',
            'emerald',
            'leather',
            'oak_wood'
        ];

        for (const item of items) {
            const give_back_count = getScore(sourceEntity, item);
            sourceEntity.runCommand(`execute as @p at @s run give @s[m=!creative] ${item} ${give_back_count}`);
        }

        sourceEntity.triggerEvent('cubc_ra_su:despawn')
    }

    const precision = 1000;

    if (id === "cubc_ra_su:register_location") {
        let {x: x, y: y, z: z} = sourceEntity.location;
        let {x: x_facing, y: y_facing} = sourceEntity.getRotation();
        x = Math.round(x * precision)
        y = Math.round(y * precision)
        z = Math.round(z * precision)

        x_facing = Math.round(x_facing * precision)
        y_facing = Math.round(y_facing * precision)

        sourceEntity.runCommand(`execute unless entity @e[r=1, family=camera] positioned ~~-1.5~ unless entity @e[r=1, family=camera] run scoreboard players set @s cubc_ra_su_safe_x ${x}`);
        sourceEntity.runCommand(`execute unless entity @e[r=1, family=camera] positioned ~~-1.5~ unless entity @e[r=1, family=camera] run scoreboard players set @s cubc_ra_su_safe_y ${y}`);
        sourceEntity.runCommand(`execute unless entity @e[r=1, family=camera] positioned ~~-1.5~ unless entity @e[r=1, family=camera] run scoreboard players set @s cubc_ra_su_safe_z ${z}`);

        sourceEntity.runCommand(`execute unless entity @e[r=1, family=camera] positioned ~~-1.5~ unless entity @e[r=1, family=camera] run scoreboard players set @s cubc_ra_su_facing_x ${x_facing}`);
        sourceEntity.runCommand(`execute unless entity @e[r=1, family=camera] positioned ~~-1.5~ unless entity @e[r=1, family=camera] run scoreboard players set @s cubc_ra_su_facing_y ${y_facing}`);
    }


    if (id === "cubc_ra_su:update_raft") {
        update_raft();
    }

    if (id === "cubc_ra_su:tp_back") {
        let tp_x = getScore(sourceEntity, "safe_x") / precision;
        let tp_y = getScore(sourceEntity, "safe_y") / precision;
        let tp_z = getScore(sourceEntity, "safe_z") / precision;

        let x_facing = getScore(sourceEntity, "facing_x") / precision;
        let y_facing = getScore(sourceEntity, "facing_y") / precision;

        if (tp_x === 0 && tp_y === 0 && tp_z === 0) {
            sourceEntity.runCommand('function cubc/ra_su/raft/kill/self');
        } else {
            sourceEntity.teleport({x: tp_x, y: tp_y, z: tp_z}, {rotation: {x: x_facing, y: y_facing}});
        }
    }
});

world.afterEvents.entitySpawn.subscribe((event) => {
    const entity = event.entity;
    if (entity.typeId.includes("cubc_ra_su:raft")) {
        entity.getComponent("health").setCurrentValue(2);
    }
});

function summonEntities(deadEntity) {
    const {x: x, y: y, z: z} = deadEntity.location;
    // Pick a radius and a small offset
    const radius = 2;
    const randomOffsetRange = 0.5; // how far from the circle edge to jitter

    // A helper function to generate a random offset within ±randomOffsetRange/2
    function randomOffset() {
        return Math.random() * randomOffsetRange - randomOffsetRange / 2;
    }

    // Angles in radians for 4 evenly spaced points (0°, 90°, 180°, 270°)
    const angles = [0, Math.PI / 2, Math.PI, (3 * Math.PI) / 2];

    // Chest types in the order you had them
    const chestTypes = [
        "cubc_ra_su:barrel",
        "cubc_ra_su:barrel",
        "cubc_ra_su:rust_chest",
        "cubc_ra_su:rust_chest",
        "cubc_ra_su:treasure_chest"
    ];

    // Loop through each angle/chest type
    for (let i = 0; i < angles.length; i++) {
        const angle = angles[i];
        const type = chestTypes[i];

        // Calculate the circular coordinates plus a tiny random offset
        const xPos = x + Math.cos(angle) * radius + randomOffset();
        const zPos = z + Math.sin(angle) * radius + randomOffset();

        // Summon each chest at its new circular position
        deadEntity.runCommand(`summon ${type} ${xPos} ${y} ${zPos}`);
    }
}

world.afterEvents.entityDie.subscribe((event) => {
    if (event.deadEntity.typeId.includes("cubc_ra_su:enemy_ship")) {
        summonEntities(event.deadEntity);
        event.deadEntity.runCommand(`tag @e[c=4, family=trash] add cubc_ra_su_still`);
        event.deadEntity.runCommand(`function cubc/ra_su/particle/fire_explosion_medium_1`);
        event.deadEntity.remove();
    }
});

system.runInterval(() => {
    const ships = world.getDimension("overworld").getEntities({
        type: "cubc_ra_su:enemy_ship"
    });
    for (const ship of ships) {
        const numberOffParticles = ((30 - ship.getComponent("health").currentValue) / 5);
        if (Math.random() < 0.25 * numberOffParticles) {
            ship.runCommand("particle cubc_ra_su:flame ~~~")
        }
    }
}, 1);

// system.runInterval(() => {
//     for (const player of world.getPlayers()) {
//         if ((player.name === "mmeester" || player.name === "CubedCreations") && player.getGameMode() === "creative") {
//             if (player.isSprinting && !player.isOnGround) {
//                 const direction = player.getViewDirection();
//                 player.applyKnockback(direction.x, direction.z, 4, direction.y * 2);
//             }
//         }
//     }
// })

