#include <Block/SpriteBlock/BeltJunction/BeltJunction.hpp>
#include <Controller/InventoryController/BeltJunctionController/BeltJunctionController.hpp>
#include <World/LocalWorld/LocalWorld.hpp>

std::vector<BeltJunction::Sprite> BeltJunction::makeSprites()
{
    std::vector<Sprite> sprites;

    for (const Side &inputSide : Side::all)
    {
        if (inputSide.isZ())
        {
            break;
        }

        Sprite sprite = {
            {},
            {{0, 0, 0, 8, 8, 8}},
            formatString("input$+", inputSide),
        };

        for (const Side &side : Side::all)
        {
            if (side == Side::Top)
            {
                sprite.texturesOnSides[side.asNumber()] = formatString("beltJunction/top/$+", inputSide.asNumber());
            }
            else if (side == Side::Bottom)
            {
                sprite.texturesOnSides[side.asNumber()] = "beltJunction/data";
            }
            else if (side == inputSide)
            {
                sprite.texturesOnSides[side.asNumber()] = "beltJunction/input";
            }
            else if (side == inputSide.opposite())
            {
                sprite.texturesOnSides[side.asNumber()] = "beltJunction/outputDefault";
            }
            else if (side.sign() == 1)
            {
                sprite.texturesOnSides[side.asNumber()] = "beltJunction/outputPos";
            }
            else
            {
                sprite.texturesOnSides[side.asNumber()] = "beltJunction/outputNeg";
            }
        }

        sprites.push_back(sprite);
    }

    return sprites;
}

BeltJunction::BeltJunction(std::string name) :
    SpriteBlock(
        name,
        "Belt Junction",
        90.0f,
        "beltJunction/icon",
        makeSprites()
    )
{
    withMetalSounds();
}

bool BeltJunction::canManuallyDig()
{
    return true;
}

void BeltJunction::onInteract(LocalWorld &world, Player &player, glm::ivec3 pos, Side side, const RGBABytes &collisionKey)
{
    if (player.isHoldingScrewdriver())
    {
        world.setBlockMeta(pos, (*world.getBlockMeta(pos) + 1) % 4, true);
        return;
    }

    player.connectController<BeltJunctionController>(
        "main:BeltJunctionController",
        world.getMachine(pos)
    );
}

bool BeltJunction::canPlace(LocalWorld &world, IWorldActor &actor, glm::ivec3 pos, Side side, uint8_t &meta)
{
    meta = actor.getSideFacing2D().opposite().asNumber();
    return true;
}