import * as mc from "@minecraft/server";
import * as utils from "../utils/index";
import { Companion } from "../npc/index";
import { VirtualInventoryComponent as VirtualInventoryComponent, DialogueComponent, OnHurtEventComponent, OnOwnerHurtEventComponent, OnOwnerDeathEventComponent, CompanionBackupComponent, CompanionShootDragonComponent, OnEntityDeathEventComponent, JigStatTrackerComponent } from "../npc/components/index";
import { QuestComponent, PlayDeadComponent, CompanionCombatSupportComponent } from "./components/index";
import { DefaultTask, PlayDeadTask } from "./tasks/index";
import { INTERACT_MENU, NON_OWNER_MENU } from "./interactMenu";
import { DIALOGUE_LIST } from "./dialogueList";
import { TRACKED_STATS } from "./trackedStats";
import { PowderedSnowComponent } from "./components/powderedSnow";
export class PlayerCompanion extends Companion {
    get Volume() {
        var _a;
        if (!this.Entity.isValid())
            return 0;
        return (_a = utils.readDynamicProperty(this.Owner, "volume")) !== null && _a !== void 0 ? _a : 1;
    }
    set Volume(v) {
        utils.writeDynamicProperty(this.Owner, "volume", utils.clamp(v, 0, 1));
    }
    get VirtualInventory() {
        return this.getComponent(VirtualInventoryComponent);
    }
    get Dialogue() {
        return this.getComponent(DialogueComponent);
    }
    get Quest() {
        return this.getComponent(QuestComponent);
    }
    get Hat() {
        return utils.readDynamicProperty(this.Entity, "hat");
    }
    set Hat(v) {
        if (v) {
            utils.writeDynamicProperty(this.Entity, "hat", v);
        }
    }
    constructor(entity, defaultTask) {
        super(entity, defaultTask);
        this.addComponent(new DialogueComponent(DIALOGUE_LIST));
        this.addComponent(new PowderedSnowComponent());
        if (!utils.readDynamicProperty(this.Entity, "owner")) {
            this.Entity.playAnimation("wave", { blendOutTime: 0.2, nextState: "root" });
            this.Entity.dimension.getPlayers({ location: this.Entity.location, maxDistance: 16 }).map(player => new utils.SafetyCheckedPlayer(player)).forEach(player => {
                var _a;
                (_a = this.Dialogue) === null || _a === void 0 ? void 0 : _a.addDialogueToQueue(player, "spawn");
            });
        }
    }
    onOwnerAssigned(newOwner) {
        newOwner.runCommand(`clear @s ${utils.GlobalNamespace.Namespace}friendship_bracelet 0 1`);
        this.broadcastEvent("tame");
    }
    onOwnerFound() {
        this.addComponent(new VirtualInventoryComponent());
        this.addComponent(new OnOwnerDeathEventComponent());
        this.addComponent(new QuestComponent());
        this.addComponent(new CompanionShootDragonComponent());
        this.addComponent(new JigStatTrackerComponent(TRACKED_STATS));
        this.addComponent(new OnEntityDeathEventComponent());
        this.addComponent(new CompanionBackupComponent(["get_item", "quest_give", "quest_reward"], ["natural_despawn"]));
        this.addComponent(new PlayDeadComponent(950));
        if (utils.readDynamicProperty(this.Entity, "combat_support"))
            this.addComponent(new CompanionCombatSupportComponent());
        this.setFilters();
        this.eventOverrides();
        this.defaultTask = DefaultTask;
        this.startTask(new this.defaultTask(this), true);
    }
    setFilters() {
        var _a, _b, _c, _d;
        (_a = this.getComponent(OnHurtEventComponent)) === null || _a === void 0 ? void 0 : _a.hurtFilters.push({
            filter: () => this.Health.currentValue <= this.getComponent(PlayDeadComponent).PlayDeadThreshold,
            event: () => { },
        }, {
            filter: (source) => Boolean(source.damagingEntity && source.damagingEntity.isValid() && source.damagingEntity.matches({ name: this.Owner.name })),
            event: () => this.broadcastEvent("hurt_by_owner"),
        }, {
            filter: (source) => source.cause !== mc.EntityDamageCause.entityExplosion && source.cause !== mc.EntityDamageCause.entityAttack,
            event: () => { },
        });
        (_b = this.getComponent(OnOwnerHurtEventComponent)) === null || _b === void 0 ? void 0 : _b.hurtFilters.push({
            filter: () => this.Health.currentValue <= this.getComponent(PlayDeadComponent).PlayDeadThreshold,
            event: () => { },
        }, {
            filter: (source) => source.cause !== mc.EntityDamageCause.entityExplosion && source.cause !== mc.EntityDamageCause.entityAttack,
            event: () => { },
        });
        (_c = this.getComponent(OnEntityDeathEventComponent)) === null || _c === void 0 ? void 0 : _c.deathFilters.push({
            filter: (event) => event.deadEntity.typeId === "minecraft:ender_dragon",
            event: () => {
                utils.waitForEvent(60, () => this.broadcastEvent("beat_minecraft"));
                this.broadcastEvent("killed.mobs");
            },
        });
        (_d = this.getComponent(OnEntityDeathEventComponent)) === null || _d === void 0 ? void 0 : _d.deathFilters.push({
            filter: (event) => { var _a; return ((_a = event.damageSource.damagingEntity) === null || _a === void 0 ? void 0 : _a.id) === this.ID; },
            event: () => {
                this.broadcastEvent("killed.mobs");
            },
        });
    }
    eventOverrides() {
        this.broadcastEvents["hurt"] = [
            () => {
                var _a, _b;
                if (!(this.CurrentTask instanceof DefaultTask) && !(this.CurrentTask instanceof PlayDeadTask)) {
                    (_a = this.CurrentTask) === null || _a === void 0 ? void 0 : _a.abort();
                }
                (_b = this.Dialogue) === null || _b === void 0 ? void 0 : _b.addDialogueToQueue(this.Owner, "hurt");
            }
        ];
        this.broadcastEvents["owner_hurt"] = [
            () => {
                var _a, _b;
                if (!(this.CurrentTask instanceof DefaultTask) && !(this.CurrentTask instanceof PlayDeadTask)) {
                    (_a = this.CurrentTask) === null || _a === void 0 ? void 0 : _a.abort();
                }
                (_b = this.Dialogue) === null || _b === void 0 ? void 0 : _b.addDialogueToQueue(this.Owner, "owner_hurt");
            }
        ];
        this.broadcastEvents["get_item"] = [
            () => utils.randomChanceEvent(3, () => { var _a; return (_a = this.Dialogue) === null || _a === void 0 ? void 0 : _a.addDialogueToQueue(this.Owner, "get_item"); })
        ];
        this.broadcastEvents["torch"] = [
            () => utils.randomChanceEvent(3, () => { var _a; return (_a = this.Dialogue) === null || _a === void 0 ? void 0 : _a.addDialogueToQueue(this.Owner, "torch"); })
        ];
        this.broadcastEvents["to_the_end"] = [
            () => {
                var _a;
                this.Entity.triggerEvent('remove_player');
                if (!utils.readDynamicProperty(this.Entity, "the_end")) {
                    this.broadcastEvent("first_the_end");
                }
                else {
                    (_a = this.Dialogue) === null || _a === void 0 ? void 0 : _a.addDialogueToQueue(this.Owner, "to_the_end");
                    utils.writeDynamicProperty(this.Entity, "the_end", true);
                }
            }
        ];
        this.broadcastEvents["to_nether"] = [
            () => {
                var _a;
                this.Entity.triggerEvent('add_player');
                if (!utils.readDynamicProperty(this.Entity, "nether")) {
                    this.broadcastEvent("first_nether");
                }
                else {
                    (_a = this.Dialogue) === null || _a === void 0 ? void 0 : _a.addDialogueToQueue(this.Owner, "to_nether");
                    utils.writeDynamicProperty(this.Entity, "nether", true);
                }
            }
        ];
        this.broadcastEvents["to_overworld"].push(() => this.Entity.triggerEvent('add_player'));
        this.broadcastEvents["quest_reward"].push(() => this.broadcastEvent("quests"));
        this.broadcastEvents["emote"] = [
            () => this.broadcastEvent("dances")
        ];
    }
    onPlayerInteract(player) {
        var _a, _b, _c, _d, _e, _f, _g;
        const item = (_a = player.Equipment) === null || _a === void 0 ? void 0 : _a.getEquipment(mc.EquipmentSlot.Mainhand);
        if ((item === null || item === void 0 ? void 0 : item.typeId) === utils.addName("friendship_bracelet") && !((_b = this.Entity.getComponent("tameable")) === null || _b === void 0 ? void 0 : _b.isTamed)) {
            (_c = this.Entity.getComponent("tameable")) === null || _c === void 0 ? void 0 : _c.tame(player.UnsafeEntity);
            player.runCommand(`clear @s ${utils.addName("friendship_bracelet")} 0 1`);
            this.broadcastEvent('tame');
            return;
        }
        if (player.id !== ((_d = this.owner) === null || _d === void 0 ? void 0 : _d.id)) {
            utils.mclog("Player Interact");
            if (!this.owner) {
                this.globalStopSound();
                (_e = this.Dialogue) === null || _e === void 0 ? void 0 : _e.clearQueue(this.Owner);
                const messageIndex = utils.getRandomInteger(0, 4);
                this.Owner.playSound(`ldz_crcomp:craftee.interact.${messageIndex}`, { volume: this.Volume });
                NON_OWNER_MENU.showMenuToPlayer(this.Owner, this, messageIndex);
            }
            return;
        }
        if (item === null || item === void 0 ? void 0 : item.typeId.includes("ldz_crcomp:hat")) {
            const hat = this.Hat ? new mc.ItemStack(this.Hat, 1) : undefined;
            (_f = this.Owner.Equipment) === null || _f === void 0 ? void 0 : _f.setEquipment(mc.EquipmentSlot.Mainhand, hat);
            this.Entity.runCommand(`replaceitem entity @s slot.armor.head 0 ${item.typeId}`);
            this.Hat = item.typeId;
            this.broadcastEvent("equip_hat");
            this.Entity.setProperty("hide_hat", false);
            return;
        }
        const menu = this.CurrentTask instanceof PlayDeadTask ? INTERACT_MENU.deathMenu : INTERACT_MENU.main;
        this.globalStopSound();
        (_g = this.Dialogue) === null || _g === void 0 ? void 0 : _g.clearQueue(this.Owner);
        const messageIndex = utils.getRandomInteger(0, 4);
        this.Owner.playSound(`ldz_crcomp:craftee.interact.${messageIndex}`, { volume: this.Volume });
        menu.showMenuToPlayer(this.Owner, this, messageIndex);
    }
    globalStopSound() {
        this.Owner.runCommand('function ldz/crcomp/global_stopsound');
    }
}
