#include <Block/SpriteBlock/LogicBox/LogicBox.hpp>
#include <Entity/PhysicsEntity/CameraEntity/Player/Player.hpp>
#include <World/LocalWorld/LocalWorld.hpp>
#include <Controller/InventoryController/LogicBoxController/LogicBoxController.hpp>

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

    for (uint8_t meta = 0; meta < 6; meta++)
    {
        Side inputSide(meta);
        Side outputSide = inputSide.opposite();

        Sprite sprite = {
            {
                "logicBox/side",
                "logicBox/side",
                "logicBox/side",
                "logicBox/side",
                "logicBox/side",
                "logicBox/side"
            },
            {{0, 0, 0, 8, 8, 8}},
            formatString("output$+", outputSide),
        };

        sprite.texturesOnSides[inputSide.asNumber()] = "logicBox/dataInput";
        sprite.texturesOnSides[outputSide.asNumber()] = "logicBox/dataOutput";

        sprites.push_back(sprite);
    }

    return sprites;
}

LogicBox::LogicBox(std::string name) :
    SpriteBlock(
        name,
        "Logic Box",
        90.0f,
        "logicBox/side",
        makeSprites()
    )
{
    withMetalSounds();
}

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

void LogicBox::onInteract(LocalWorld &world, Player &player, glm::ivec3 pos, Side side, const RGBABytes &collisionKey)
{
    if (player.isHoldingScrewdriver())
    {
        uint8_t meta = *world.getBlockMeta(pos);
        world.setBlockMeta(pos, (meta + 1) % 6, true);

        return;
    }

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

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