import { world, ItemStopUseAfterEvent, ItemStartUseAfterEvent, Player, ItemStack, ItemDurabilityComponent, EntityEquippableComponent, EquipmentSlot, EntityProjectileComponent, system, EntityComponentTypes, EntityInventoryComponent } from '@minecraft/server';
import { Server } from '../../libs/Core/index.js'
import { ActionbarTimer } from '../utils/ActionbarTimer.js';

export class EchoBeamer {
    /** @type {Map<Player, number: time>} */
    #players = new Map();
    /** @type {Map<Player, ActionbarTimer} */
    #loadingIndicators = new Map();

    constructor() {
        this.#initEvents();
    }

    #initEvents() {
        world.afterEvents.itemStartUse.subscribe(this.#itemStartUse.bind(this));
        world.afterEvents.itemStopUse.subscribe(this.#itemEndUse.bind(this));
    }


    /**
     * @param {ItemStartUseAfterEvent} e 
     * @returns {void}
     */
    #itemStartUse(e) {
        if (e.itemStack.typeId !== 'plank_waao:echo_beamer') return;
        e.source.runCommandAsync('playsound item.plank_waao.echo_beamer.charge');
        this.#players.set(e.source, Date.now());
        this.#loadingIndicators.set(e.source, new ActionbarTimer(e.source, 20, 'bar'));
    }

    /**
     * @param {ItemStopUseAfterEvent} e 
     * @returns {void}
     */
    #itemEndUse(e) {
        if (this.#loadingIndicators.get(e.source)) {
            this.#loadingIndicators.get(e.source)?.stop();
            this.#loadingIndicators.delete(e.source);
        }
        if (e.source.getComponent('equippable').getEquipment(EquipmentSlot.Mainhand)?.typeId !== 'plank_waao:echo_beamer') return;
        if (!this.#players.has(e.source)) return;

        const duration = Date.now() - this.#players.get(e.source);
        if (duration < 1000) return;
        e.source.runCommandAsync('playsound item.plank_waao.echo_beamer.release');

        this.#shoot(e.source, e.itemStack);
    }

    /**
     * Shoot arrow
     * @param {Player} player - the shooter
     * @param {ItemStack} item - the bow
     * @returns {void}
     */
    #shoot(player, item) {
        this.#decrementDurability(player, item, 1);
        system.runTimeout(() => {
            Server.entityShootProjectile('plank_waao:echo_beamer_projectile', player, 1, { gravity: 0 });
        }, 9);


    }

    /**
     * Decrements the durability of the item in hand
     * @param {Player} player 
     * @param {ItemStack} item 
     * @param {number} amount
     */
    #decrementDurability(player, item, amount) {
        if (player.getGameMode() == 'creative') return;
        /** @type {ItemDurabilityComponent} */
        let durabilityComponent = item.getComponent('durability');
        /** @type {EntityEquippableComponent} */
        const equippableComponent = player.getComponent("equippable");

        if (durabilityComponent.damage + amount >= durabilityComponent.maxDurability) {
            equippableComponent.setEquipment(EquipmentSlot.Mainhand);
            return;
        }
        durabilityComponent.damage = durabilityComponent.damage + amount;
        equippableComponent.setEquipment(EquipmentSlot.Mainhand, item);
    }
}

export const strikerBow = new EchoBeamer();