import * as mc from "@minecraft/server";
import * as utils from "../../utils/index";
import * as comp from "../components/index";
import { BotBase } from "../bot";
export const MINER_MAX_FUEL = 64;
export const MINER_FUEL_ITEM = "minecraft:coal";
const SECONDS_PER_BLOCK = 3.0;
export class MinerBot extends BotBase {
    constructor() {
        super(...arguments);
        this.active = false;
    }
    get Active() {
        return this.active;
    }
    set Active(v) {
        if (!this.isValid())
            return;
        this.active = v;
        this.setProperty("active", v);
    }
    onConstructed() {
        super.onConstructed();
        this.dimension.playSound(utils.addName("entity.bot.ambient"), this.location);
        this.addActorComponent(comp.BotFuelComponent, { fuelItem: MINER_FUEL_ITEM, max: MINER_MAX_FUEL });
        this.addActorComponent(comp.BlockSnapComponent, { angle: 90 });
        this.addActorComponent(comp.MineBlockComponent, {
            type: "block",
            useTileDrops: true,
            onUnbreakable: (block) => {
                this.dimension.playSound(utils.addName("entity.drill_bot.hit_unbreakable"), this.location);
                utils.mclog(`${this.ActorId} hit unbreakable block ${block === null || block === void 0 ? void 0 : block.typeId}`, this.ActorId);
                this.Active = false;
            },
        });
        // transfer fuel from player used item to this bot
        if (!this.hasTag("spawned")) {
            utils.waitForEvent(2, () => {
                const tags = this.getTags();
                tags.forEach(tag => {
                    var _a;
                    if (tag.includes('fuelType'))
                        return;
                    if (tag.includes('fuel')) {
                        const newFuel = Number(tag.replace('fuel', ''));
                        (_a = this.getActorComponent(comp.BotFuelComponent)) === null || _a === void 0 ? void 0 : _a.initialFuel(newFuel);
                        this.addTag("spawned");
                    }
                });
            });
        }
        this.active = this.getProperty("active");
        if (this.Active)
            this.drillLoop();
    }
    onNonFuelInteract(player) {
        this.Active = !this.Active;
        if (!this.Active)
            player.dimension.playSound(utils.addName("entity.bot.deactivate"), player.location);
        if (this.Active)
            player.dimension.playSound(utils.addName("entity.bot.activate"), player.location, { volume: 0.8 });
        this.drillLoop();
    }
    onFuelRestored() {
        this.playAnimation("fuel_up");
    }
    onFuelExhausted() {
        this.runCommand(`stopsound @a ldz_240927:entity.miner_bot.move`);
        this.dimension.playSound(utils.addName("entity.bot.power_down"), this.location);
    }
    async drillLoop() {
        if (!this.Active)
            return;
        while (this.isValid() && this.Fuel > 0 && this.Active) {
            //this.teleport(this.location.center());
            this.teleport({ x: Math.floor(this.location.x) + 0.5, y: this.location.y, z: Math.floor(this.location.z) + 0.5 });
            await this.moveToBlock(this.location);
            await this.breakBlock();
            this.Fuel--;
        }
        this.Active = false;
    }
    async moveToBlock(origin) {
        var _a;
        if (this.isValid() && ((_a = this.getActorComponent(comp.MineBlockComponent)) === null || _a === void 0 ? void 0 : _a.isBlockInDirection(this.getViewDirection())))
            return;
        for (let delta = 0; delta <= 1; delta += 0.1) {
            if (!this.isValid())
                return;
            this.teleport(origin.lerp(origin.add(this.getViewDirection()), delta));
            await utils.waitForTicks(0);
        }
        await utils.waitForLoopEvent(5, () => {
            return !this.isValid() || this.dimension.getBlockFromRay(this.location, utils.Vector3.DOWN, { includePassableBlocks: false, maxDistance: 1 }) !== undefined;
        });
    }
    async breakBlock() {
        var _a, _b, _c, _d, _e, _f;
        if (!this.isValid())
            return;
        let canMine1 = false;
        let canMine2 = false;
        do {
            canMine1 = (_b = (_a = this.getActorComponent(comp.MineBlockComponent)) === null || _a === void 0 ? void 0 : _a.isBlockInDirection(this.getViewDirection())) !== null && _b !== void 0 ? _b : false;
            canMine2 = (_d = (_c = this.getActorComponent(comp.MineBlockComponent)) === null || _c === void 0 ? void 0 : _c.isBlockInDirection(this.getViewDirection(), this.location.up())) !== null && _d !== void 0 ? _d : false;
            if (canMine1 || canMine2) {
                await utils.waitForTicks(SECONDS_PER_BLOCK * 20);
                if (!this.Active)
                    return;
                (_e = this.getActorComponent(comp.MineBlockComponent)) === null || _e === void 0 ? void 0 : _e.breakBlockInDirection(this.getViewDirection());
                (_f = this.getActorComponent(comp.MineBlockComponent)) === null || _f === void 0 ? void 0 : _f.breakBlockInDirection(this.getViewDirection(), this.location.up());
            }
            await utils.waitForTicks(10);
        } while (canMine1 || canMine2);
    }
}
utils.Actor.makeActors({ type: "ldz_240927:miner_bot" }, MinerBot);
// register if player uses bot spawn egg
mc.world.afterEvents.itemUseOn.subscribe((event) => {
    if (event.itemStack.typeId === utils.addName("miner_bot_dummy") + "_spawn_egg" && event.source instanceof mc.Player) {
        const location = new utils.Vector3(event.block.center()).up(0.5);
        const lore = event.itemStack.getLore();
        let storedFuel = 0;
        if (lore[1]) {
            storedFuel = Number(lore[1].replace(comp.lineColor, '').split(' ')[0]);
        }
        else {
            storedFuel = MINER_MAX_FUEL * 0.25;
        }
        rotateDummy(event.source, location, storedFuel);
    }
});
// correct the rotation of the dummy after it is spawned
async function rotateDummy(source, location, fuel) {
    let hasRotated = false;
    while (!hasRotated) {
        await utils.waitForTicks(1);
        // get real bot entity
        const dummies = utils.getEntitiesSafe(source.dimension, { location: location, closest: 1, maxDistance: 1.25, type: utils.addName("miner_bot_dummy") });
        // set rotation variable on dummy based on real bot rotation
        if (dummies[0]) {
            const dummy = dummies[0];
            const rot = dummy.getRotation().y + 180;
            source.runCommand(`summon ldz_240927:miner_bot ${location.x} ${location.y} ${location.z} ~ ${rot}`);
            utils.waitForTicks(1);
            const bot = utils.getEntitiesSafe(source.dimension, { location: location, closest: 1, maxDistance: 1.25, type: utils.addName("miner_bot") });
            if (bot[0]) {
                bot[0].addTag('fuel' + fuel);
                const tameable = bot[0].getComponent("tameable");
                if (tameable) {
                    tameable.tame(source);
                }
            }
            hasRotated = true;
        }
    }
}
