import { Direction, ItemStack, world } from "@minecraft/server";
import { getItemInHand, getItemInInventory, setItemInInventory, spillInventory, splitItem, translate } from "../util/miscUtils";
import { blockEntityManager } from "../blockEntitiesManager";
import { SuppEntities } from "../reg/suppEntities";
import { vecAdd } from "../util/mthUtils";
import { SuppStates } from "../reg/suppStates";
import { McItems } from "../reg/mcItems";
import { UIBuilder } from "../util/uiBuilder";
import { SuppItems } from "../reg/suppItems";
import { randomVectorInCone, spawnConfettiParticles } from "./confettiStuff";
import { SuppParticles } from "../reg/suppParticles";
import { projectileManager } from "../projectilesManager";
import { McEntities } from "../reg/mcEntities";
blockEntityManager.registerEntityBlock(SuppEntities.Present, [
    "razz_sup:present_white" /* SuppBlocks.PresentWhite */,
    "razz_sup:present_light_gray" /* SuppBlocks.PresentLightGray */,
    "razz_sup:present_gray" /* SuppBlocks.PresentGray */,
    "razz_sup:present_black" /* SuppBlocks.PresentBlack */,
    "razz_sup:present_brown" /* SuppBlocks.PresentBrown */,
    "razz_sup:present_red" /* SuppBlocks.PresentRed */,
    "razz_sup:present_orange" /* SuppBlocks.PresentOrange */,
    "razz_sup:present_yellow" /* SuppBlocks.PresentYellow */,
    "razz_sup:present_lime" /* SuppBlocks.PresentLime */,
    "razz_sup:present_green" /* SuppBlocks.PresentGreen */,
    "razz_sup:present_cyan" /* SuppBlocks.PresentCyan */,
    "razz_sup:present_light_blue" /* SuppBlocks.PresentLightBlue */,
    "razz_sup:present_blue" /* SuppBlocks.PresentBlue */,
    "razz_sup:present_purple" /* SuppBlocks.PresentPurple */,
    "razz_sup:present_magenta" /* SuppBlocks.PresentMagenta */,
    "razz_sup:present_pink" /* SuppBlocks.PresentPink */,
    "razz_sup:present" /* SuppBlocks.Present */
], {
    isOptional() {
        return true;
    },
    onBroken(blockPermutation, pos, be) {
        //mega dumb
        let toDrop = new ItemStack(blockPermutation.type.id);
        const recipient = be.getDynamicProperty(PRESENT_RECIPIENT);
        const sender = be.getDynamicProperty(PRESENT_SENDER);
        //yet another bug. thanks mojank. Block items will always be marked as iStackable. cant use dyn properties..... ffs
        // if (recipient) toDrop.setDynamicProperty(presentRecipient, recipient);
        //  if (sender) toDrop.setDynamicProperty(presentSender, sender);
        //const bundle =toDrop.getComponent(ItemComponentTypes.Enchantable) as ItemEnchantableComponent;
        // be.dimension.spawnItem(toDrop, vecAdd(pos, 0.5, 0.5, 0.5));
        //drop the entire content of the inventory since we cant preserve it
        spillInventory(be);
    }
});
const ANYONE = "@e";
function showPresentGUI(player, targetSetter, failAction) {
    const players = world.getAllPlayers();
    const playerNames = players.map(player => player.name);
    const ui = UIBuilder.create("present")
        .buttonsPage()
        .noBody()
        .onFail(failAction)
        .actionButton("anyone", b => {
        targetSetter(ANYONE);
    }, "textures/razz/sup/gui/present/players")
        .with(b => {
        for (const name of playerNames) {
            b.actionButton(name, b => {
                targetSetter(name);
            }, "textures/razz/sup/gui/present/player", { text: name });
        }
    })
        .actionButton("other_player", context => context
        .childUi()
        .formPage()
        .text("player_name")
        .onSubmit((r, b) => {
        const string = r.text[0];
        targetSetter(string.length == 0 ? ANYONE : string);
    })
        .build())
        .build();
    ui.open(player);
}
const PRESENT_RECIPIENT = "razz_sup:recipient";
const PRESENT_SENDER = "razz_sup:sender";
export const PresentComponent = {
    beforeOnPlayerPlace(event) {
        event.permutationToPlace = event.permutationToPlace.withState(SuppStates.Packed, false)
            .withState(SuppStates.UpsideDown, event.face == Direction.Down);
    },
    onPlayerInteract(event) {
        const block = event.block;
        const player = event.player;
        const be = blockEntityManager.getOrCreateBlockEntity(block);
        const packed = block.permutation.getState(SuppStates.Packed);
        //add item
        if (!packed) {
            const item = getItemInHand(player);
            //TODO: add blacklist
            if (item) {
                //sound
                showPresentGUI(player, (target) => {
                    be.setDynamicProperty(PRESENT_RECIPIENT, target);
                    be.setDynamicProperty(PRESENT_SENDER, player.name);
                    const maxCount = getMaxAcceptedCount(item);
                    const remainder = splitItem(player, item, maxCount);
                    setItemInInventory(be, remainder);
                    block.setPermutation(block.permutation
                        .withState(SuppStates.Packed, true));
                    block.dimension.playSound("dig.cloth", block.center(), { volume: 1, pitch: 1.3 });
                    player.onScreenDisplay.setActionBar(target == ANYONE ?
                        translate("message", "present.anyone") : translate("message", "present.packed", [target]));
                }, () => {
                    be.remove();
                });
            }
        }
        else {
            const recipient = be.getDynamicProperty(PRESENT_RECIPIENT);
            const sender = be.getDynamicProperty(PRESENT_SENDER);
            if (!recipient || !sender || player.name == recipient || recipient == ANYONE || sender == player.name) {
                //unpack
                block.setPermutation(block.permutation.withState(SuppStates.Packed, false));
                block.dimension.playSound("dig.cloth", block.center(), { volume: 1, pitch: 1.3 });
                const item = getItemInInventory(be);
                if (item) {
                    setItemInInventory(be, undefined);
                    const isUpsideDown = block.permutation.getState(SuppStates.UpsideDown);
                    let spawnPosition = vecAdd(block.location, 0.5, isUpsideDown ? 0 : 0.9, 0.5);
                    block.dimension.spawnParticle(SuppParticles.PresentPoof, spawnPosition);
                    deployPresentContent(block, item, spawnPosition);
                    be.remove();
                }
            }
            else {
                //display message
                player.onScreenDisplay.setActionBar(translate("message", "present.not_for_you", [recipient]));
            }
        }
    }
};
function getMaxAcceptedCount(item) {
    const id = item.type.id;
    if (id.endsWith("_spawn_egg") || id == McItems.TNT || id == SuppItems.ConfettiPopper || id == SuppItems.Bomb) {
        return 1;
    }
    return 64;
}
function deployPresentContent(block, item, spawnPosition) {
    const id = item.type.id;
    if (id.endsWith("_spawn_egg")) {
        const entityId = id.substring(0, id.length - 10);
        try {
            block.dimension.spawnEntity(entityId, spawnPosition);
            return;
        }
        catch (e) {
        }
    }
    else if (id == SuppEntities.HatStand || id == McEntities.ArmorStand) {
        block.dimension.spawnEntity(id, spawnPosition);
        return;
    }
    else if (id == McItems.TNT) {
        const tnt = block.dimension.spawnEntity(id, spawnPosition);
        tnt.triggerEvent("from_explosion");
        return;
    }
    else if (id == SuppItems.ConfettiPopper) {
        spawnConfettiParticles({ x: 0, y: 1, z: 0 }, spawnPosition, block.dimension, 0.65);
        return;
    }
    else if (id == SuppItems.Bomb) {
        const v = randomVectorInCone({ x: 0, y: 1, z: 0 }, 0);
        projectileManager.shootProjectile(block.dimension, SuppEntities.BombProjectile, spawnPosition, v, 4, SuppItems.Bomb);
        return;
    }
    block.dimension.spawnItem(item.clone(), spawnPosition);
}
