import { ItemStack, MolangVariableMap, TicksPerSecond, world } from "@minecraft/server";

import { EntityObject, EntityRuntime } from "../global_api/EntityRuntime";
import { Vector3 } from "../global_api/Math";
import { portalReturn } from "../ui/portal";
/**
 * BOSS: [
 *    [ITEM_ID, MIN_AMOUNT, MAX_AMOUNT]
 * ]
 */
const RECOMPENSE_ITEMS = {
    "pixell_bbo:burazazu": [
        ["pixell_bbo:core_burazazu", 2, 3],
        ["pixell_bbo:souls", 36, 42],
    ],
    "pixell_bbo:craterus": [
        ["pixell_bbo:core_craterus", 2, 3],
        ["pixell_bbo:souls", 63, 64],
        ["pixell_bbo:souls", 1, 8],
    ],
    "pixell_bbo:sweetgabriel": [
        ["pixell_bbo:core_gabriel", 2, 3],
        ["pixell_bbo:souls", 50, 64],
    ],

    "pixell_bbo:hades": [
        ["pixell_bbo:core_hades", 2, 3],
        ["pixell_bbo:souls", 64],
        ["pixell_bbo:souls", 8, 12],
    ],
    "pixell_bbo:unknown": [
        ["pixell_bbo:core_unknown", 2, 3],
        ["pixell_bbo:souls", 28, 36],
    ],
    "pixell_bbo:ares": [
        ["pixell_bbo:core_ares", 2, 3],
        ["pixell_bbo:souls", 42, 50],
    ],
};

class Junkbox extends EntityObject {
    timeWithoutBoss = 0;
    onSpawn() {
        this.data["location"] = this.getEntity().location;
        this.data["finished"] = false;
    }

    onTick() {
        const entity = this.getEntity();
        entity.teleport(this.data["location"]);
        entity.dimension.playSound(this.data["music"], entity.location);

        entity.dimension
            .getEntities({
                location: entity.location,
                maxDistance: 256,
                type: "minecraft:enderman",
            })
            .forEach((e) => e.remove());

        const bosses = entity.dimension.getEntities({
            location: entity.location,
            maxDistance: 256,
            type: this.data["boss"],
        });
        if (!this.data.finished) {
            bosses.forEach((boss) => {
                if (boss && boss.location) {
                    this.data["chestSpawn"] = {
                        x: boss.location.x,
                        z: boss.location.z,
                        y: boss.location.y + 1,
                    };
                }
            });
        }

        if (bosses.length == 0) {
            this.timeWithoutBoss++;
        }

        if (this.timeWithoutBoss > 5 || this.data.finished) {
            let portalLocation = this.data["chestSpawn"];
            if (!(portalLocation && portalLocation.x)) {
                portalLocation = this.data["spawnBoss"];
            }

            if (!this.data.finished) {
                let chestBlock = entity.dimension.getBlockFromRay(
                    { x: portalLocation.x, y: portalLocation.y + 8, z: portalLocation.z },
                    new Vector3(0, -1, 0),
                    { maxDistance: 30 }
                );
                chestBlock = chestBlock.block;
                if (chestBlock) {
                    //portalLocation = (chestBlock?.block?.above()?.location) ?? portalLocation;
                    const items = [];
                    const recompenseItems = RECOMPENSE_ITEMS[this.data["boss"]];
                    if (typeof recompenseItems == "string") {
                        items.push(new ItemStack(recompenseItems, 1));
                    } else if (recompenseItems instanceof Array) {
                        recompenseItems.forEach((i) => {
                            let amount = Math.round(((i[2] ?? i[1]) - i[1]) * Math.random()) + i[1];
                            items.push(new ItemStack(i[0], amount));
                        });
                    }

                    this.data["portalLoc"] = portalLocation;

                    const upLoc = {
                        x: portalLocation.x,
                        y: portalLocation.y,
                        z: portalLocation.z + 5,
                    };
                    items.forEach((i) => {
                        this.getEntity().dimension.spawnItem(i, upLoc);
                    });
                }
            }
            const portalMolang = new MolangVariableMap();

            portalMolang.setFloat("variable.portal_size", 2.2);

            const selfLocation = {
                x: portalLocation.x,
                y: portalLocation.y,
                z: portalLocation.z - 3,
            };
            this.data.finished = true;

            if (this.getActiveTime() % (TicksPerSecond * 1.2) == 0) {
                entity.dimension.spawnParticle(
                    this.data["boss"] + "_portal",
                    selfLocation,
                    portalMolang
                );
            }

            const closePlayers = entity.dimension
                .getEntities({
                    location: selfLocation,
                    maxDistance: 3,
                    type: "minecraft:player",
                })
                .forEach((player) => {
                    let players = entity.dimension.getEntities({
                        location: entity.location,
                        type: "minecraft:player",
                        maxDistance: 128,
                    });

                    if (players.length == 1) {
                        world.setDynamicProperty(this.data["key"], 132);
                    }

                    player.addTag("pixell_bbo:finish_fight");

                    player.setDynamicProperty("lastFinishFight", Date.now());

                    if (player.hasTag("pixell_bbo:finish_fight")) {
                        const portalShowPropName = "ninja:portal_ui_show";

                        /**
                         * @type {boolean | undefined}
                         */
                        const playerShowCooldown = player.getDynamicProperty(portalShowPropName);

                        if (!playerShowCooldown) {
                            player.setDynamicProperty(portalShowPropName, true);

                            portalReturn(player);
                        }
                    }
                });

            const farPlayers = entity.dimension
                .getEntities({
                    location: selfLocation,
                    maxDistance: 8,
                    minDistance: 4,
                    type: "minecraft:player",
                })
                .forEach((player) => {
                    player.addTag("pixell_bbo:finish_fight");

                    if (player.hasTag("pixell_bbo:finish_fight")) {
                        const portalShowPropName = "ninja:portal_ui_show";

                        player.setDynamicProperty(portalShowPropName, false);
                    }
                });
        }

        entity.dimension
            .getEntities({
                tags: ["pixell_bbo:idle_player"],
                maxDistance: 256,
                location: entity.location,
            })
            .forEach((e) => {
                e.teleport(this.data["spawnPlayer"], {
                    facingLocation: this.data["spawnBoss"],
                });
                e.removeEffect("slow_falling");
                e.removeEffect("slowness");
                e.removeEffect("darkness");
                e.removeTag("pixell_bbo:idle_player");
            });
    }
}

EntityRuntime.register("pixell_bbo:junkbox", Junkbox);
