import { EntityDamageCause, Player, system, world, Entity, ItemStack } from "@minecraft/server";
import { Entities } from "./Entities";
import { movePlayerAway, placeCircusTent, getRandomBetween } from "../utils/utils";

world.afterEvents.playerInteractWithEntity.subscribe((event) => {
    const { player, itemStack, target: entity } = event;

    if (entity.typeId == Entities.circus_wheel) {
        entity.triggerEvent("wheel:spin");
        spinWheel(player, entity);
    }
});

world.afterEvents.dataDrivenEntityTrigger.subscribe((event) => {
    const { entity, eventId } = event;

    if (entity.typeId == Entities.circus_wheel) {
        switch (eventId) {
            case "clown:move_player_away": {
                movePlayerAway(entity, 1.7);

                break;
            }
            case "minecraft:entity_spawned": {
                let number = Math.round(Math.random() * 3);

                const rotations = ["wheel:north", "wheel:south", "wheel:west", "wheel:east"];

                system.runTimeout(() => {
                    const worldEntities = world.getAllPlayers()[0]?.dimension.getEntities() ?? [];

                    if (worldEntities.includes(entity)) {
                        entity.triggerEvent(rotations[number]);
                    }
                }, 0.1 * 20);

                break;
            }
        }
    }
});

world.afterEvents.entitySpawn.subscribe((event) => {
    const { entity } = event;

    if (entity.typeId == "px_hc:circus_wheel") {
        const nearbyEntities = entity.dimension.getEntities({
            location: entity.location,
            minDistance: 0.1,
            maxDistance: 80,
        });

        if (nearbyEntities.length > 0) {
            if (
                nearbyEntities.some(
                    (e) =>
                        e.matches({ families: ["circus_wheel"] }) ||
                        e.matches({ families: ["placeholder"] })
                )
            ) {
                entity?.remove();
            }
        }
    }
});

export const clowns = new Map([
    [1, "px_hc:clown"],
    [2, "px_hc:ringmaster"],
    [3, "px_hc:acrobat_juggler"],
    [4, "px_hc:illusionist"],
    [5, "px_hc:strongman"],
    [6, "px_hc:harley_quinn"],
    [7, "px_hc:butcher_clown"],
    [8, "px_hc:pyro"],
    [9, "px_hc:stilt_walker"],
    [10, "px_hc:jester"],
]);

/**
 *
 * @param {Player} player
 * @param {Entity} entity
 */
function spinWheel(player, entity) {
    if (player.getDynamicProperty("spawn_sequence") == undefined) {
        player.setDynamicProperty("spawn_sequence", 0);
    }

    const spawn_sequence = player.getDynamicProperty("spawn_sequence");

    player.setDynamicProperty("spawn_sequence", Math.min(11, spawn_sequence + 1));

    let number =
        player.getDynamicProperty("spawn_sequence") < 11
            ? player.getDynamicProperty("spawn_sequence")
            : Math.max(1, Math.round(Math.random() * 10));

    const currentNumber = entity.getProperty("wheel:number");

    if (number == currentNumber) {
        number = Math.min(10, number + 1);

        if (player.getDynamicProperty("spawn_sequence") < 11) {
            player.setDynamicProperty("spawn_sequence", number);
        }
    }

    entity?.setProperty("wheel:number", number);

    placeCircusTent(player, clowns.get(number), 6);

    /*  system.runTimeout(() => {
        world.sendMessage("§eNumber: " + number);
    }, 2.5 * 20); */

    system.runTimeout(() => {
        entity?.setProperty("wheel:despawn", true);
    }, 5 * 20);
}

const drops = new Map([
    [
        1,
        {
            item: "minecraft:rotten_flesh",
            count: 1,
        },
    ],
    [
        2,
        {
            item: "minecraft:diamond",
            count: 2,
        },
    ],
    [
        3,
        {
            item: "minecraft:iron_ingot",
            count: 10,
        },
    ],
    [
        4,
        {
            item: "minecraft:gold_ingot",
            count: 10,
        },
    ],
]);

const randomEvent = new Map([
    [
        1,
        {
            exec: function (deadEntity, damageSource) {
                explode(deadEntity, damageSource);
            },
        },
    ],
    [
        2,
        {
            exec: function (deadEntity, damageSource) {
                lightning(deadEntity, damageSource);
            },
        },
    ],
]);

world.afterEvents.entityDie.subscribe((event) => {
    const { deadEntity, damageSource } = event;
    const damagingEntity = damageSource.damagingEntity;

    if (deadEntity.typeId == "px_hc:clown_box") {
        const random = getRandomBetween(1, 6);

        if (random < drops.size + 1) {
            const item = new ItemStack(drops.get(random).item, drops.get(random).count);
            deadEntity.dimension.spawnItem(item, deadEntity.location);
        } else {
            const randomN = getRandomBetween(1, 2);

            randomEvent.get(randomN)?.exec(deadEntity, damagingEntity);
        }
    }
});

/**
 *
 * @param {Entity} deadEntity
 * @param {Entity} damageSource
 */
function explode(deadEntity, damageSource) {
    const { dimension, location } = deadEntity;

    dimension.createExplosion(location, 4, { breaksBlocks: false, source: deadEntity });
}

/**
 *
 * @param {Entity} deadEntity
 * @param {Entity} damageSource
 */
function lightning(deadEntity, damageSource) {
    const dimension = deadEntity.dimension;
    const location = deadEntity.location;

    const nearbyPlayers = dimension.getPlayers({ location: location, maxDistance: 10 });

    for (let player of nearbyPlayers) {
        dimension.spawnEntity("minecraft:lightning_bolt", player.location);
    }
}
