import {
    EntityInventoryComponent,
    MolangVariableMap,
    Player,
    system,
    TicksPerSecond,
    world,
} from "@minecraft/server";

import { EntityObject, EntityRuntime } from "../global_api/EntityRuntime";

import { resetPlayerGamemode, setPlayerArenaGamemode } from "../entities/Player";
import { Utils } from "../entities/Utils";
import { ArenaMap, buildArena } from "../ui/portal";
import { resetPlayerLastEnteredPortal, setPlayerLastEnteredPortal } from "../utils/utils";
import { BossFightArena } from "./BossFightArena";

export const Arenas = {
    "pixell_bbo:craterus_portal": new BossFightArena(
        "pixell_bbo:craterus",
        "pixell_bbo:ar/craterus",
        "",
        1000,
        [["pixell_bbo:souls", 56]]
    ),
    "pixell_bbo:ares_portal": new BossFightArena(
        "pixell_bbo:ares",
        "pixell_bbo:ar/ares",
        "",
        5000,
        [["pixell_bbo:souls", 40]]
    ),
    "pixell_bbo:hades_portal": new BossFightArena(
        "pixell_bbo:hades",
        "pixell_bbo:ar/hades",
        "",
        10000,
        [["pixell_bbo:souls", 64]]
    ),
    "pixell_bbo:burazazu_portal": new BossFightArena(
        "pixell_bbo:burazazu",
        "pixell_bbo:ar/burazazu",
        "",
        15000,
        [["pixell_bbo:souls", 32]]
    ),
    "pixell_bbo:unknown_portal": new BossFightArena(
        "pixell_bbo:unknown",
        "pixell_bbo:ar/unknown",
        "",
        20000,
        [["pixell_bbo:souls", 24]]
    ),
    "pixell_bbo:sweetgabriel_portal": new BossFightArena(
        "pixell_bbo:sweetgabriel",
        "pixell_bbo:ar/sweetgabriel",
        "",
        25000,
        [["pixell_bbo:souls", 48]]
    ),
};

const locID = (position) => `${position.x}_${position.y}_${position.z}`;

class Portal extends EntityObject {
    onTick() {
        super.onTick();

        if (this.getActiveTime() % (TicksPerSecond * 5) == 0) {
            this.getEntity().dimension.playSound(
                "pixell_bbo.portal.idle",
                this.getEntity().location
            );
        }

        const dimension = this.getEntity().dimension;

        const block = dimension.getBlock(this.getEntity().location);

        if (!block?.isValid()) return;

        if (block.typeId != "pixell_bbo:portal") {
            //this.getEntity().remove();

            return;
        }

        if (system.currentTick % (TicksPerSecond * 1.5) == 0) {
            const isActivated = this.getEntity().getProperty("self:activated");

            const portalMolang = new MolangVariableMap();

            portalMolang.setFloat("variable.portal_size", isActivated ? 5.0 : 1.5);

            const center = block.center();

            center.y += 1.5;

            block.dimension.spawnParticle(this.data["target"], center, portalMolang);
        }

        /** @type {Player[]} */
        const players = block.dimension
            .getEntities({
                location: block.center(),
                maxDistance: 1.25,
                type: "minecraft:player",
            })
            .filter((player) => {
                if (player?.hasTag("pixell_bbo:finish_fight")) {
                    this.setProperty("self:enter", false);

                    Utils.applyForce(player, { x: 0, y: 2, z: 2 });

                    Utils.post(() => {
                        player.removeTag("pixell_bbo:finish_fight");
                    }, 2);

                    resetPlayerGamemode(player);
                    //clearPlayerFog(player);
                    resetPlayerLastEnteredPortal(player);

                    //teleportar a entidade faz ela ser removida por alguma razão
                    this.getEntity().teleport({
                        x: block.x,
                        y: block.y + 10,
                        z: block.z,
                    });

                    return false;
                }
                return true;
            });

        const targetOffset = {
            x: this.data["targetX"] ?? 0,
            z: this.data["targetZ"] ?? 0,
        };

        const portalDest = world.getDynamicProperty(
            "px_bbo:portal_" + targetOffset.x + "_" + targetOffset.z
        );

        if (portalDest == 132) {
            this.getEntity().remove();
            return;
        }

        const meLoc = locID(block.center());
        const enablePortal = this.getProperty("self:activated") && this.getProperty("self:enter");

        if (players.length > 0 && !portalDest) {
            const areana = Arenas[this.data["target"]];

            world.setDynamicProperty(this.data["target"], meLoc);

            if (enablePortal) {
                const player = players[0];

                this.setProperty("self:enter", false);

                //  areana.build(players[0], this.data["targetX"], this.data["targetZ"]);

                buildArena(player, ArenaMap.get(this.data["target"]));

                setPlayerLastEnteredPortal(player, this.getEntity());
            }
        } else if (portalDest && players.length > 0 && enablePortal) {
            players[0].addEffect("slow_falling", TicksPerSecond * 2);

            players[0].dimension.playSound("pixell_bbo.portal.teleport", players[0].location);

            players[0].teleport(
                {
                    x: portalDest.x,
                    z: portalDest.z + 5,
                    y: portalDest.y,
                },
                {
                    dimension: world.getDimension("the_end"),
                }
            );

            setPlayerArenaGamemode(players[0]);
        }
    }

    /**
     * @param {Player} player
     * @param {string} itemID
     * @param {*} amount
     */
    hasItems(player, itemID, amount = 1) {
        const container = player.getComponent(EntityInventoryComponent.componentId).container;

        for (let i = 0; i < container.size; i++) {
            const slot = container.getSlot(i);

            if (slot.hasItem() && slot.typeId == itemID) {
                amount -= slot.amount;
            }

            if (amount <= 0) return true;
        }

        return false;
    }
}

EntityRuntime.register("pixell_bbo:portal", Portal);

world.beforeEvents.worldInitialize.subscribe((e) => {
    e.blockComponentRegistry.registerCustomComponent("pixell_bbo:randomize_portal", {
        onTick: ({ block }) => {
            const keys = Object.keys(Arenas);

            const targetID =
                keys[
                    Math.max(0, Math.min(keys.length - 1, Math.floor(Math.random() * keys.length)))
                ];

            const entities = block.dimension.getEntities({
                location: block.center(),
                maxDistance: 2,
                type: "pixell_bbo:portal",
            });

            if (entities.length == 0) {
                const entity = block.dimension.spawnEntity("pixell_bbo:portal", {
                    x: block.center().x,
                    y: block.center().y + 1,
                    z: block.center().z,
                });

                const prop = targetID.split(":")[1].split("_")[0];

                entity.setProperty("self:portal_type", prop);

                while (true) {
                    let x = Math.round(Math.random() * 120) - 20;

                    let z = Math.round(Math.random() * 120) - 20;

                    if (!world.getDynamicProperty("px_bbo:portal_" + x + "_" + z)) {
                        entity.setDynamicProperty("targetX", x);

                        entity.setDynamicProperty("targetZ", z);

                        break;
                    }
                }

                entity.setDynamicProperty("target", targetID);

                block.setType("minecraft:air");
            }
        },
    });
});
