import * as utils from "../../utils/index";
import * as comp from "../components/index";
import { BotBase } from "../bot";
const LOG_TYPES = [
    {
        typeId: "minecraft:acacia_log",
        texture: "textures/ldz/240927/ui/lumber/acacia_log",
        langKey: "tile.log.acacia.name",
    },
    {
        typeId: "minecraft:birch_log",
        texture: "textures/ldz/240927/ui/lumber/birch_log",
        langKey: "tile.log.birch.name",
    },
    {
        typeId: "minecraft:cherry_log",
        texture: "textures/ldz/240927/ui/lumber/cherry_log",
        langKey: "tile.cherry_log.name",
    },
    {
        typeId: "minecraft:crimson_stem",
        texture: "textures/ldz/240927/ui/lumber/crimson_stem",
        langKey: "tile.crimson_stem.name",
    },
    {
        typeId: "minecraft:dark_oak_log",
        texture: "textures/ldz/240927/ui/lumber/dark_oak_log",
        langKey: "tile.log.big_oak.name",
    },
    {
        typeId: "minecraft:jungle_log",
        texture: "textures/ldz/240927/ui/lumber/jungle_log",
        langKey: "tile.log.jungle.name",
    },
    {
        typeId: "minecraft:mangrove_log",
        texture: "textures/ldz/240927/ui/lumber/mangrove_log",
        langKey: "tile.mangrove_log.name",
    },
    {
        typeId: "minecraft:oak_log",
        texture: "textures/ldz/240927/ui/lumber/oak_log",
        langKey: "tile.log.oak.name",
    },
    {
        typeId: "minecraft:pale_oak_log",
        texture: "textures/ldz/240927/ui/lumber/pale_oak_log",
        langKey: "tile.pale_oak_log.name",
    },
    {
        typeId: "minecraft:spruce_log",
        texture: "textures/ldz/240927/ui/lumber/spruce_log",
        langKey: "tile.log.spruce.name",
    },
    {
        typeId: "minecraft:warped_stem",
        texture: "textures/ldz/240927/ui/lumber/warped_stem",
        langKey: "tile.warped_stem.name",
    },
];
const GRID = [
    new utils.Vector3({ x: 0, y: 0, z: -1 }),
    new utils.Vector3({ x: 0, y: 0, z: 0 }),
    new utils.Vector3({ x: 0, y: 0, z: 1 }),
    new utils.Vector3({ x: 1, y: 0, z: -1 }),
    new utils.Vector3({ x: 1, y: 0, z: 0 }),
    new utils.Vector3({ x: 1, y: 0, z: 1 }),
    new utils.Vector3({ x: -1, y: 0, z: -1 }),
    new utils.Vector3({ x: -1, y: 0, z: 0 }),
    new utils.Vector3({ x: -1, y: 0, z: 1 }),
];
export class LumberBot extends BotBase {
    constructor() {
        super(...arguments);
        this.canceled = false;
        this.state = this.getProperty(utils.addName("state"));
        this.logType = "minecraft:oak_log";
    }
    get State() {
        return this.state;
    }
    set State(v) {
        this.state = v;
        this.setProperty(utils.addName("state"), v);
    }
    get Owner() {
        if (!this.isValid())
            return;
        if (this.owner)
            return this.owner;
        const tame = this.getComponent("tameable");
        if (tame && tame.tamedToPlayerId) {
            const owner = utils.getAllPlayersSafe().find(player => player.id === tame.tamedToPlayerId);
            this.owner = owner;
            return owner;
        }
    }
    onConstructed() {
        super.onConstructed();
        this.addActorComponent(comp.AutotameComponent);
        this.addActorComponent(comp.VirtualInventoryComponent);
        //this.addActorComponent(comp.BotFuelComponent, {fuelItem: LUMBER_FUEL_ITEM, max: LUMBER_MAX_FUEL});
        this.addActorComponent(comp.MineBlockComponent, {
            type: "block",
            onItemCollected: (item, block) => {
                var _a;
                (_a = this.getActorComponent(comp.VirtualInventoryComponent)) === null || _a === void 0 ? void 0 : _a.addItem(item);
            },
        });
        this.subscribe("logging_started", () => this.State = "chopping");
        this.subscribe("logging_success", () => this.State = "carrying");
        this.subscribe("logging_failure", () => this.State = "idle");
        this.subscribe("player_hit", this.cancelLogging.bind(this));
    }
    onInteract(player) {
        if (this.State !== "carrying") {
            player.playSound(utils.addName("menu.bot.open"));
            this.showLoggingMenu(player);
        }
        else {
            this.giveInventory(player);
        }
    }
    //public onFuelExhausted(): void {
    //    this.triggerEvent("default_owner_follow");
    //}
    cancelLogging() {
        this.canceled = true;
        this.removeActorComponent(comp.NavigateComponent);
        this.removeActorComponent(comp.MoveToOwnerComponent);
        this.State = "idle";
        this.triggerEvent("default_owner_follow");
    }
    showLoggingMenu(player) {
        new utils.MenuBuilder({
            type: "buttons",
            title: { translate: utils.addName("menu.lumber_bot.title") },
            contents: [
                {
                    text: { translate: utils.addName("menu.button.cancel") },
                    texture: "textures/blocks/barrier",
                    //onClick: this.cancelLogging.bind(this),
                    onClick: () => {
                        player.playSound(utils.addName("menu.bot.select_stay"));
                        this.cancelLogging.bind(this);
                    }
                },
                ...LOG_TYPES.map((log, index) => {
                    return {
                        text: { translate: log.langKey },
                        texture: log.texture,
                        onClick: () => {
                            player.playSound(utils.addName("menu.bot.confirm"));
                            this.State = "logging";
                            this.setProperty(utils.addName("held_block"), index);
                            this.logLoop(log.typeId);
                        }
                    };
                }),
            ],
        }).showMenuToPlayer(player);
    }
    async logLoop(logType) {
        var _a;
        this.logType = logType;
        this.canceled = false;
        while (this.isValid() && this.logType === logType && !this.canceled) {
            utils.mclog("Log Loop", this.ActorId);
            this.State = "logging";
            this.runCommand(`stopsound @a ldz_240927:entity.bot.hover`);
            this.removeActorComponent(comp.NavigateComponent);
            const targetBlock = await utils.searchForBlock(this.dimension, this.location, 50, { block: this.logType });
            if (targetBlock && !this.canceled) {
                const result = await new Promise((resolve) => {
                    this.dimension.playSound(utils.addName("entity.bot.hover"), this.location);
                    this.addActorComponent(comp.NavigateComponent, {
                        destination: targetBlock.location,
                        navNodeId: utils.addName("nav_node"),
                        onSuccess: () => resolve(true),
                        onFailure: () => resolve(false),
                    });
                });
                this.runCommand(`stopsound @a ldz_240927:entity.bot.hover`);
                this.removeActorComponent(comp.NavigateComponent);
                if (result && !this.canceled) {
                    await this.cutDownTree(targetBlock);
                }
                else if (this.isValid()) {
                    this.raiseEvent("logging_failure");
                    continue;
                }
            }
            await utils.waitForTicks(30);
            if ((_a = this.Owner) === null || _a === void 0 ? void 0 : _a.isValid()) {
                try {
                    await this.moveToOwner();
                    if (this.Owner.isValid())
                        this.giveInventory(this.Owner);
                }
                catch (error) {
                    utils.mcerror("Failed to move to owner", this.ActorId);
                    break;
                }
            }
            await utils.waitForTicks(20);
        }
    }
    async cutDownTree(targetBlock) {
        if (this.isValid()) {
            this.raiseEvent("logging_started");
            await utils.waitForTicks(10);
            let origin = new utils.Vector3(this.getTreeBase(targetBlock).location);
            let logs = this.getLogs(this.logType, origin, this.dimension);
            while (logs.length && this.isValid()) {
                for (const block of logs) {
                    origin = new utils.Vector3(block.location);
                    this.chopLog(block);
                }
                origin = origin.up();
                logs = this.getLogs(this.logType, origin, this.dimension);
                await utils.waitForTicks(5);
            }
            await utils.waitForTicks(10);
            //this.Fuel--;
            this.raiseEvent("logging_success");
        }
    }
    getTreeBase(block) {
        var _a;
        try {
            while (block && ((_a = block.below()) === null || _a === void 0 ? void 0 : _a.matches(block.typeId))) {
                block = block.below();
            }
            return block;
        }
        catch (error) {
            return block;
        }
    }
    getLogs(blockName, origin, dimension) {
        var _a, _b, _c, _d;
        const arr = [];
        for (const position of GRID) {
            const block = dimension.getBlock(origin.add(position));
            if (block === null || block === void 0 ? void 0 : block.matches(blockName)) {
                arr.push(block);
                if ((_a = block.north()) === null || _a === void 0 ? void 0 : _a.matches(blockName))
                    utils.addUniqueToArray(arr, block.north());
                if ((_b = block.south()) === null || _b === void 0 ? void 0 : _b.matches(blockName))
                    utils.addUniqueToArray(arr, block.south());
                if ((_c = block.east()) === null || _c === void 0 ? void 0 : _c.matches(blockName))
                    utils.addUniqueToArray(arr, block.east());
                if ((_d = block.west()) === null || _d === void 0 ? void 0 : _d.matches(blockName))
                    utils.addUniqueToArray(arr, block.west());
            }
        }
        return arr;
    }
    chopLog(block) {
        var _a;
        (_a = this.getActorComponent(comp.MineBlockComponent)) === null || _a === void 0 ? void 0 : _a.breakBlock(block);
    }
    async moveToOwner() {
        this.removeActorComponent(comp.MoveToOwnerComponent);
        return new Promise((resolve, reject) => {
            this.dimension.playSound(utils.addName("entity.bot.hover"), this.location);
            this.addActorComponent(comp.MoveToOwnerComponent, {
                startEvent: "add_move_to_owner",
                stopEvent: "remove_move_to_owner",
                owner: this.Owner,
                onSuccess: () => {
                    this.runCommand(`stopsound @a ldz_240927:entity.bot.hover`);
                    this.removeActorComponent(comp.MoveToOwnerComponent);
                    resolve();
                },
                onFailure: reject,
            });
        });
    }
    giveInventory(player) {
        const virtualInventory = this.getActorComponent(comp.VirtualInventoryComponent);
        if (virtualInventory) {
            virtualInventory.getAllItems(true).forEach(item => {
                if (player.Inventory.emptySlotsCount > 0) {
                    player.playSound("random.pop");
                    player.Inventory.addItem(item);
                }
                else {
                    this.dimension.spawnItem(item, this.location);
                }
            });
        }
        this.State = "idle";
    }
}
utils.Actor.makeActors({ type: "ldz_240927:lumber_bot" }, LumberBot);
