import { EntityComponentTypes, ItemComponentTypes, ItemStack, world } from "@minecraft/server";
import { expansionEvents, timerManager } from "./serverExpansion";
import { Vector3Utils } from "./vector3Utils";
import * as util from './serverUtils';
let charging_start_text = { rawtext: [
        { translate: "accessibility.purerain_dino.message.charging_start" }
    ]
};
let charging_end_text = { rawtext: [
        { translate: "accessibility.purerain_dino.message.charging_end" }
    ]
};
class GunManager {
    constructor() {
        this.Guns = new Map();
        this.Shooters = new Map();
        this.bulletList = new Map();
        this.reloading = new Map();
        //取消攻击实体造成的耐久损耗，此处需额外在数驱自定义组件中注册'purerain_dino:luncher'组件
        world.beforeEvents.worldInitialize.subscribe((args => {
            args.itemComponentRegistry.registerCustomComponent('purerain_dino:luncher', {
                onBeforeDurabilityDamage(args) {
                    args.durabilityDamage = 0;
                },
            });
        }));
        world.afterEvents.itemStartUse.subscribe((args => {
            const item = args.itemStack;
            const gunComp = this.Guns.get(item.typeId);
            if (gunComp) {
                const player = args.source;
                const duraComp = item.getComponent(ItemComponentTypes.Durability);
                const magazine = new ItemStack(gunComp.magazine);
                if (duraComp) {
                    if (duraComp.damage < duraComp.maxDurability) {
                        duraComp.damage += 1;
                        this.shoot(player, gunComp);
                        util.item.setItem(player, item);
                        if (gunComp.isAuto) {
                            const timerId = timerManager.createTimer(() => {
                                const duraComp = item.getComponent(ItemComponentTypes.Durability);
                                if (duraComp && duraComp.damage < duraComp.maxDurability) {
                                    duraComp.damage += 1;
                                    this.shoot(player, gunComp);
                                    util.item.setItem(player, item);
                                }
                            }, { time: gunComp.interval, repeat: true });
                            this.Shooters.set(player.id, timerId);
                        }
                    }
                    else if (duraComp.damage = duraComp.maxDurability) {
                        if (this.reloading.has(player.id))
                            return;
                        if (util.item.hasItem(player, magazine)) {
                            args.source.onScreenDisplay.setActionBar(charging_start_text);
                            const timer = timerManager.createTimer(() => {
                                const itemNow = util.item.getEquipment(player);
                                if (itemNow?.matches(item.typeId) && util.item.hasItem(player, magazine)) {
                                    args.source.onScreenDisplay.setActionBar(charging_end_text);
                                    duraComp.damage = 0;
                                    util.item.setItem(player, item);
                                    args.source.runCommand("/clear @s purerain_dino:plasma_battery 0 1");
                                }
                                this.reloading.delete(player.id);
                            }, { time: gunComp.reload });
                            this.reloading.set(player.id, timer);
                        }
                    }
                }
            }
        }));
        world.afterEvents.itemStopUse.subscribe((args => {
            const player = args.source;
            const timerId = this.Shooters.get(player.id);
            if (timerId) {
                timerManager.removeTimer(timerId);
                this.Shooters.delete(player.id);
            }
        }));
        expansionEvents.selectedItemChange.subscribe(args => {
            const player = args.player;
            if (this.reloading.has(player.id)) {
                const timer = this.reloading.get(player.id);
                timerManager.removeTimer(timer);
                this.reloading.delete(player.id);
            }
        });
        world.afterEvents.projectileHitEntity.subscribe(args => {
            const proj = args.projectile;
            this.bulletList.forEach((list, typeId) => {
                if (list.includes(proj.id)) {
                    const gunComp = this.Guns.get(typeId);
                    const hit = args.getEntityHit().entity;
                    const healthComp = hit?.getComponent(EntityComponentTypes.Health);
                    if (healthComp) {
                        if ((healthComp.currentValue - 20) > healthComp.effectiveMin) {
                            healthComp.setCurrentValue(healthComp.currentValue - gunComp.damage);
                        }
                        else {
                            healthComp.setCurrentValue(healthComp.effectiveMin);
                        }
                    }
                    proj.remove();
                    list = list.filter(id => id !== proj.id);
                    this.bulletList.set(typeId, list);
                }
            });
        });
        world.afterEvents.projectileHitBlock.subscribe(args => {
            const proj = args.projectile;
            this.bulletList.forEach((list, typeId) => {
                if (list.includes(proj.id)) {
                    proj.remove();
                    list = list.filter(id => id !== proj.id);
                    this.bulletList.set(typeId, list);
                }
            });
        });
    }
    addGun(typeId, comp1) {
        let comp2 = {
            magazine: comp1.magazine,
            bullet: comp1.bullet !== undefined ? comp1.bullet : 'minecraft:arrow',
            interval: comp1.interval !== undefined ? comp1.interval : 20,
            damage: comp1.damage !== undefined ? comp1.damage : 1,
            reload: comp1.reload !== undefined ? comp1.reload : 36,
            isAuto: comp1.isAuto !== undefined ? comp1.isAuto : true,
            power: comp1.power !== undefined ? comp1.power : 1,
            gravity: comp1.gravity !== undefined ? comp1.gravity : 0,
            uncertainty: comp1.uncertainty !== undefined ? comp1.uncertainty : 0,
            itemId: typeId
        };
        this.Guns.set(typeId, comp2);
        this.bulletList.set(typeId, []);
    }
    getGun(typeId) {
        return this.Guns.get(typeId);
    }
    shoot(player, gunComp) {
        const shootLoc = player.getHeadLocation();
        const dimension = player.dimension;
        const bulletEntity = dimension.spawnEntity(gunComp.bullet, shootLoc);
        const projComp = bulletEntity.getComponent(EntityComponentTypes.Projectile);
        if (projComp) {
            let list = this.bulletList.get(gunComp.itemId);
            if (!list)
                return;
            list.push(bulletEntity.id);
            this.bulletList.set(gunComp.itemId, list);
            projComp.owner = player;
            projComp.gravity = gunComp.gravity;
            let launchV3 = player.getViewDirection();
            launchV3 = Vector3Utils.scale(launchV3, gunComp.power);
            projComp.shoot(launchV3, { uncertainty: gunComp.uncertainty });
        }
        else {
            console.error(`实体 ${bulletEntity.typeId} 不存在 'minecraft:projectile' 组件！`);
            bulletEntity.remove();
        }
    }
}
export const gunMng = new GunManager();
