import * as mc from "@minecraft/server";
import * as utils from "../utils/index";
import { DestructEventComponent, DestructOnRemoveEventComponent, NPCBase, OnHurtEventComponent } from "../npc/index";
import { HatOptionsComponent } from "./components/hatOptions";
import { WornHat } from "./worn_hat";
export class Hat extends NPCBase {
    constructor() {
        super(...arguments);
        this.owner = utils.getRandomArrayEntry(utils.getAllPlayersSafe());
    }
    get Hat() {
        return utils.readDynamicProperty(this.Entity, "hat");
    }
    set Hat(v) {
        if (v) {
            utils.writeDynamicProperty(this.Entity, "hat", v);
            this.Entity.setProperty("hat_index", v.hatIndex);
            this.Entity.setProperty("height_offset", v.heightOffset);
        }
    }
    get HatIndex() {
        return this.Entity.getProperty("hat_index");
    }
    get Owner() {
        return this.owner;
    }
    onConstructed() {
        super.onConstructed();
        utils.waitForEvent(1, () => {
            var _a;
            this.addComponent(new HatOptionsComponent());
            this.addComponent(new OnHurtEventComponent());
            this.addComponent(new DestructEventComponent());
            this.addComponent(new DestructOnRemoveEventComponent());
            (_a = this.getComponent(OnHurtEventComponent)) === null || _a === void 0 ? void 0 : _a.hurtFilters.push({
                filter(source) {
                    return source.damagingEntity instanceof mc.Player;
                },
                event: (event) => {
                    this.onHurt(new utils.SafetyCheckedPlayer(event.damageSource.damagingEntity));
                },
            });
        });
    }
    onOwnerFound() {
        var _a;
        (_a = this.getComponent(OnHurtEventComponent)) === null || _a === void 0 ? void 0 : _a.hurtFilters.push({
            filter(source) {
                return source.damagingEntity instanceof mc.Player;
            },
            event: (event) => {
                this.onHurt(new utils.SafetyCheckedPlayer(event.damageSource.damagingEntity));
            },
        });
    }
    onHurt(player) {
        var _a;
        const hat = this.Hat;
        if (hat) {
            const item = new mc.ItemStack(hat.itemId, 1);
            const lore = WornHat.LoreTable[hat.itemId];
            if (lore)
                item.setLore(lore);
            this.Entity.dimension.spawnItem(item, this.Entity.location);
            const hatList = (_a = utils.readDynamicProperty(player, "obtainedHats")) !== null && _a !== void 0 ? _a : [];
            utils.addUniqueToArray(hatList, hat.itemId);
            utils.writeDynamicProperty(player, "obtainedHats", hatList);
        }
        this.Entity.dimension.playSound("ldz_crcomp:entity.hat.hurt", this.Entity.location);
        this.destructor("Hurt");
    }
}
export function initializeHat() {
    Hat.instantiateNPC({ type: "ldz_crcomp:hat" }, Hat);
    mc.system.afterEvents.scriptEventReceive.subscribe(event => {
        if (event.id === "ldz_crcomp:hat_reset" && event.sourceEntity) {
            utils.writeDynamicProperty(event.sourceEntity, "obtainedHats", []);
        }
    });
    mc.system.afterEvents.scriptEventReceive.subscribe(event => {
        if (event.id === "ldz_crcomp:hat_give" && event.sourceEntity) {
            const player = new utils.SafetyCheckedEntity(event.sourceEntity);
            Object.keys(WornHat.LoreTable).forEach(key => {
                var _a;
                const item = new mc.ItemStack(key, 1);
                item.setLore(WornHat.LoreTable[key]);
                (_a = player.Inventory) === null || _a === void 0 ? void 0 : _a.addItem(item);
            });
        }
    });
    spawnHats();
}
async function spawnHats() {
    while (true) {
        const promises = utils.getAllPlayersSafe().map(player => spawnHat(player));
        promises.push(utils.waitForTicks(12000));
        await Promise.all(promises);
    }
}
async function spawnHat(player) {
    var _a;
    if (!((_a = utils.readDynamicProperty(player, "settings.hat_spawn")) !== null && _a !== void 0 ? _a : true) || !mc.world.gameRules.doMobSpawning)
        return;
    await utils.waitForTicks(utils.getRandomInteger(10, 20) * 1200);
    return new Promise((resolve) => {
        const callback = (event) => {
            var _a;
            const validMobs = ["minecraft:cow", "minecraft:sheep", "minecraft:pig", "minecraft:chicken", "minecraft:skeleton", "minecraft:zombie", "minecraft:enderman"];
            if (event.entity.isValid() && validMobs.includes(event.entity.typeId) && event.entity.dimension.getPlayers({ closest: 1 }).find(p1 => p1.id === player.id)) {
                if ((_a = utils.readDynamicProperty(player, "settings.hat_notify")) !== null && _a !== void 0 ? _a : true) {
                    player.playSound("ldz_crcomp:event.hat_spawn");
                    player.sendMessage({ translate: "ldz_crcomp:craftee.message.hat_nearby" });
                }
                player.dimension.spawnEntity("ldz_crcomp:hat", event.entity.location);
                event.entity.remove();
                mc.world.afterEvents.entitySpawn.unsubscribe(callback);
                utils.abortEvents(player.id + "hat_spawn");
                resolve();
            }
        };
        utils.mclog(`${player.name} waiting for mob to spawn to replace with hat`);
        mc.world.afterEvents.entitySpawn.subscribe(callback);
        utils.waitForEvent(5 * 1200, () => {
            utils.mcwarn(`${player.name} failed to find mob to replace with hat`);
            mc.world.afterEvents.entitySpawn.unsubscribe(callback);
            resolve();
        }, player.id + "hat_spawn");
    });
}
