import * as mc from "@minecraft/server";
import * as lib from '../lib/lib';
import { highlightBlock } from "../lib/lib";
import { connectToPipes, disconnectFromPipes } from "../lib/mana_network";

const MAX_HEIGHT = 4;
const MAX_FILL = 10;
const MIN_HEIGHT = 2;

export class manaTankManager {
    static beforeplace(data) {
        const block = data.block;
        const blockId = data.permutationToPlace.type.id;

        let height = 0;
        let origin;

        //find origin block
        for (let index = 0; index < 16; index++) {
            if (block.below(index).hasTag("pb_scraft_mana_tank")) {
                height++;
            }
        }
        height = height % MAX_HEIGHT;
        origin = block.below(height);

        if (height > 0) {
            mc.system.runTimeout(() => {
                applyBlocksFromOrigin(origin, height);
            }, 1)
        }
    }

    static interact(data) {
        const block = data.block;
        const player = data.player;

        const mainhand = player.getComponent(mc.EntityEquippableComponent.componentId).getEquipmentSlot(mc.EquipmentSlot.Mainhand);
        const heldItem = mainhand.getItem();
        if (heldItem == undefined) return;

        if (heldItem.typeId == "pb_scraft:tank_block") {
            const origin = getOrigin(block);

            let topBlock = origin;
            for (let index = 0; index < MAX_HEIGHT; index++) {
                if (topBlock.isAir) {
                    topBlock.setPermutation(mc.BlockPermutation.resolve("pb_scraft:tank_block"));
                    block.dimension.playSound("dig.stone", topBlock.center());
                    if (player.getGameMode() != mc.GameMode.creative) mainhand.setItem(lib.itemManager.reduceAmount(heldItem, 1));
                    applyBlocksFromOrigin(origin, index);
                    return;
                }
                topBlock = topBlock.above();
            }
        }

        if (heldItem.typeId == "pb_scraft:mana_meter") {
            const origin = getOrigin(block);
            const capacity = getCapacity(origin);
            player.dimension.playSound("pb_scraft.interact_contraption", data.block.location);
            player.sendMessage("§u[Magic]§r Mana Tank: " + capacity.fill * 100 + "/" + capacity.max * 100 + " Mana");
        }
    }

    static tick(data) {
        const block = data.block;
        const location = block.center();
        const fuel = block.permutation.getState("pb_scraft:fuel");
        for (let index = 0; index < fuel; index++) {
            mc.world.getDimension(block.dimension.id).spawnParticle("pb_scraft:tank_ambient", location);
        }
    }

    static destroy(data) {
        const block = data.block;
        const type = data.destroyedBlockPermutation.type.id;

        let origin;
        let height;
        //tank base block destroyed
        if(type == "pb_scraft:mana_tank")
        {
            origin = block;
            disconnectFromPipes(origin, data.destroyedBlockPermutation);
            height = getHeight(origin);
        }
        //tank top block destroyed
        if(type == "pb_scraft:mana_tank_top")
        {
             let below = block.below();
            //block above break, below might be converted - lets see how
            if(below.type.id == "pb_scraft:mana_tank")
            {
                disconnectFromPipes(below, below.permutation);
                below.setPermutation(mc.BlockPermutation.resolve("pb_scraft:tank_block")) //tank would be 1 block high, convert back to normal tank block
            }

            if(below.type.id == "pb_scraft:mana_tank_top")
            {
                const fuel = below.permutation.getState("pb_scraft:fuel");
                below.setPermutation(mc.BlockPermutation.resolve("pb_scraft:mana_tank_top", { 'pb_scraft:height': 1, 'pb_scraft:fuel': fuel }))   //tank is at least 2 block high, below block is the new top
            }
        }
    }
}

function applyBlocksFromOrigin(origin, height) {
    for (let index = 0; index <= height; index++) {
        let tankblock = origin.above(index);

        if (index == 0) {
            tankblock.setPermutation(mc.BlockPermutation.resolve("pb_scraft:mana_tank", { 'pb_scraft:fuel': 0 }));  //base
            tankblock.setPermutation(connectToPipes(tankblock, tankblock.permutation));
        }
        if (index == height) tankblock.setPermutation(mc.BlockPermutation.resolve("pb_scraft:mana_tank_top", { 'pb_scraft:height': 1, 'pb_scraft:fuel': 0 }))   //top
        if (index != 0 && index < height) tankblock.setPermutation(mc.BlockPermutation.resolve("pb_scraft:mana_tank_top", { 'pb_scraft:height': 0, 'pb_scraft:fuel': 0 }))  //middle


        highlightBlock(tankblock);
    }

    //applyMana(origin, height, lib.randomWholeNum(0, (height+1) * 5));
}

//export functions
export function getOrigin(block)
{
    if(block.type.id == "pb_scraft:mana_tank") return block;
    for (let index = 1; index < MAX_HEIGHT; index++) {
        if (block.below(index).type.id == "pb_scraft:mana_tank") return block.below(index);
    }
}

export function getHeight(origin) {
    let height = 1;
    for (let index = 1; index < MAX_HEIGHT; index++) {
        if (origin.above(index).type.id == "pb_scraft:mana_tank_top") height++;
        else break;
    }

    return height;
}

export function getCapacity(origin) {
    const height = getHeight(origin);
    let fill = 0;

    for (let index = 0; index < height; index++) {
        let tankblock = origin.above(index);
        fill = fill + tankblock.permutation.getState("pb_scraft:fuel");
    }

    return { fill: fill, max: height * MAX_FILL }
}

export function addMana(origin, amount) {
    const height = getHeight(origin);
    const capacity = getCapacity(origin);

    if (capacity.fill >= capacity.max) return false;    //tank is full
    if (capacity.max - capacity.fill < amount) return false;   //tank cannot manage amount

    //apply new fill level from origin upwards
    let fill = amount + capacity.fill;
    let current_fill = MAX_FILL;

    for (let index = 0; index < height; index++) {
        let tankblock = origin.above(index);
        if (fill >= MAX_FILL) current_fill = MAX_FILL;
        else current_fill = fill;
        tankblock.setPermutation(tankblock.permutation.withState('pb_scraft:fuel', current_fill));
        fill = fill - current_fill;
    }

    return true;
}

export function removeMana(origin, amount) {
    const height = getHeight(origin);
    const capacity = getCapacity(origin);

    if (capacity.fill < amount) return false;   //tank cannot manage amount

    //apply new fill level from origin upwards
    let fill = capacity.fill - amount;
    let current_fill = MAX_FILL;

    for (let index = 0; index < height; index++) {
        let tankblock = origin.above(index);
        if (fill >= MAX_FILL) current_fill = MAX_FILL;
        else current_fill = fill;
        tankblock.setPermutation(tankblock.permutation.withState('pb_scraft:fuel', current_fill));
        fill = fill - current_fill;
    }

    return true;
}