import { BlockPermutation, Direction, EntityComponentTypes, system, world } from "@minecraft/server";
import { SuppItems } from "../reg/suppItems";
import { lengthSquared, random } from "../util/mthUtils";
import { SuppEntities } from "../reg/suppEntities";
import { projectileManager } from "../projectilesManager";
import { damageItemIfInSurvival, getItemInInventory, playSwingArm, setItemInInventory, setItemInMainHand, splitItem } from "../util/miscUtils";
import { getBlockOfItem, isMultiBlock } from "../util/blockProperties";
import { attemptPlacingAt } from "../util/placementUtils";
import { offsetVec } from "../util/dirUtils";
import { SuppParticles } from "../reg/suppParticles";
import { worldProxy } from "../worldProxy";
import { configs } from "../configs";
projectileManager.registerProjectile(SuppEntities.SlingshotProjectile, {
    onHitBlock(entity, hit) {
        const hitPos = hit.hitBlock;
        const hitFace = hit.hitFace;
        const entityId = entity.id;
        const entityPos = entity.location;
        system.runTimeout(() => {
            const e = world.getEntity(entityId);
            if (e) {
                placeBlockFromSlingshot(e, hitPos, hitFace, entityPos);
                e.remove();
            }
            else {
                console.log("Projectile hit block, but entity is gone");
            }
        }, 0);
    },
    onTick(entity, prevPos) {
        if (worldProxy.getTickTime() % 5 == 0) {
            const vel = projectileManager.getProjectileVelocity(entity);
            if (lengthSquared(vel) > 0.1) {
                entity.dimension.spawnParticle(SuppParticles.SmokeRing, offsetVec(prevPos, Direction.Up, 0.25));
            }
        }
    }
});
world.afterEvents.itemStartUse.subscribe((event) => {
    const item = event.itemStack.typeId;
    if (item == SuppItems.Slingshot) {
        const player = event.source;
        player.playAnimation("animation.razz_sup.player.third_person.use_slingshot", { stopExpression: "!query.is_using_item", blendOutTime: 0 });
        player.dimension.playSound("razz_sup.slingshot.charge", player.location, { volume: 0.5, pitch: 1.2 });
    }
});
//same as in item prop
const useDurationTicks = 30 * 20;
//same as in animation ( a bit more)
const ticksToFullyCharge = 14;
world.afterEvents.itemReleaseUse.subscribe((event => {
    const itemStack = event.itemStack;
    if (itemStack.typeId == SuppItems.Slingshot) {
        const player = event.source;
        const usedFor = useDurationTicks - event.useDuration; //idk why it counts down from 80
        if (usedFor <= 5)
            return;
        const [projItem, slot] = findProjectile(player);
        if (projItem) {
            const power = getPowerForTime(usedFor) * configs.slingshotScalar.getValue();
            const projectileEntity = projectileManager.shootProjectileFromEntity(player, power, SuppEntities.SlingshotProjectile);
            //TODO: actual slingshot sound hee
            projectileEntity.dimension.playSound("razz_sup.slingshot.release", projectileEntity.location, {
                volume: 0.5,
                pitch: random(1, 1.2)
            });
            const remainderAmmo = splitItem(player, projItem, 1, slot);
            damageItemIfInSurvival(player, itemStack);
            setItemInInventory(projectileEntity, remainderAmmo);
            setItemInMainHand(projectileEntity, remainderAmmo);
            playSwingArm(player);
            //TODO: sound
        }
    }
}));
function findProjectile(player) {
    const inv = player.getComponent(EntityComponentTypes.Inventory);
    if (inv && inv.container) {
        for (let i = 0; i < inv.container.size; i++) {
            const item = inv.container.getItem(i);
            if (item && isValidItem(item)) {
                return [item, i];
            }
        }
    }
    return [undefined, -1];
}
export const SlingshotComponent = {
    onCompleteUse(event) {
        //shoot
    },
    onUse(event) {
        //TODO: play charge animation
    }
};
function isValidItem(item) {
    const id = item.typeId;
    const blockOfItem = getBlockOfItem(item);
    return blockOfItem != undefined && !isMultiBlock(BlockPermutation.resolve(blockOfItem.id));
}
//put in slingshot class
function placeBlockFromSlingshot(entity, hitBlockPos, hitFace, oldEntityPos) {
    const level = entity.dimension;
    const hitBlock = level.getBlock(hitBlockPos);
    const item = getItemInInventory(entity);
    if (hitBlock != undefined && item) {
        try {
            let perm = BlockPermutation.resolve(getBlockOfItem(item).id);
            if (attemptPlacingAt(hitBlock, hitFace, perm)) {
                level.playSound("dig.stone", hitBlock.center());
                return;
            }
        }
        catch (e) {
        }
        //spawn loot
        level.playSound("random.pop", oldEntityPos);
        level.spawnItem(item, oldEntityPos);
    }
}
function getPowerForTime(charge) {
    let f = charge / ticksToFullyCharge;
    f = (f * f + f * 2) / 3;
    if (f > 1) {
        f = 1;
    }
    return f;
}
