#include <Block/SpriteBlock/Bricks/Bricks.hpp>
#include <Utilities/Extern.hpp>
#include <World/LocalWorld/LocalWorld.hpp>
#include <bitset>
#include <random>
#include <FrameDrawer/FrameDrawer.hpp>
#include <ChunkWindow/ChunkWindow.hpp>

std::vector<Bricks::Sprite> Bricks::makeSprites(std::string iconName)
{
    std::vector<Sprite> sprites;

    int i;
    for (i=0; i<16; i++)
    {
        sprites.push_back(
            Sprite{
                {iconName, iconName, iconName, iconName, iconName, iconName},
                {{0, 0, 0, 8, 8, 8}},
                formatString("$+", std::bitset<4>(i)),
            }
        );
    }

    return sprites;
}

Bricks::Bricks(std::string name, std::string displayName, float hardness, std::string texName) :
    SpriteBlock(name, displayName, hardness, texName, makeSprites(texName))
{
    withStoneSounds();
}

void Bricks::onPlaced(LocalWorld &world, Chunk &chunk, glm::ivec3 pos)
{
    for (const Side &side : Side::all)
    {
        onNeighborUpdated(world, pos, side);
    }
}

void Bricks::onNeighborUpdated(LocalWorld &world, glm::ivec3 pos, Side side)
{
    if (side.isZ())
    {
        return;
    }

    uint8_t oldMeta = *world.getBlockMeta(pos);
    uint8_t newMeta = oldMeta & ~side.mask();

    if (world.getBlockAt(pos + side.out())->isFullyOpaque())
    {
        newMeta |= side.mask();
    }

    if (newMeta != oldMeta)
    {
        world.setBlockMeta(pos, newMeta);
    }
}

bool Bricks::isFullyOpaque()
{
    return true;
}

void Bricks::onDesignerInitializing(BlockSpriteDesigner &designer, ScriptEngine &engine)
{
    designer.useFallbackScript("dyedBricks.lua");
}