#include <Block/SpriteBlock/ElectricLamp/ElectricLamp.hpp>
#include <World/LocalWorld/LocalWorld.hpp>

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

    static const char *colorNames[7] = {
        "red",
        "green",
        "yellow",
        "blue",
        "magenta",
        "cyan",
        "white"
    };

    for (uint8_t meta = 0; meta < 16; meta++)
    {
        int colorIndex = (meta & 7) - 1;
        if (colorIndex == -1) colorIndex = 0;

        const char *activationName = (meta & metaOn) ? "on" : "off";
        const char *activationNameCap = (meta & metaOn) ? "On" : "Off";
        const char *colorName = colorNames[colorIndex];

        std::string texName = formatString("electricLamp/$+/$+", activationName, colorName);

        sprites.push_back({
            {texName, texName, texName, texName, texName, texName},
            {{0, 0, 0, 8, 8, 8}},
            formatString("$+$+", colorName, activationNameCap)
        });
    }

    return sprites;
}

ElectricLamp::ElectricLamp(std::string name) :
    SpriteBlock(
        name,
        "Electric Lamp",
        15.0f,
        "electricLamp/off/white",
        makeSprites()
    )
{
    withGlassSounds();
}

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

void ElectricLamp::onPlaced(LocalWorld &world, Chunk &chunk, glm::ivec3 pos)
{
    world.setBlockMeta(pos, metaRed | metaGreen | metaBlue);
}

glm::vec3 ElectricLamp::getLightColor(uint8_t meta)
{
    // If the lamp is not on, don't emit any light.
    if ((meta & metaOn) == 0)
    {
        return glm::vec3(0.0f);
    }

    // Otherwise, emit light in the specified color.
    glm::vec3 result(0.15f, 0.15f, 0.15f);
    int i;
    for (i=0; i<3; i++)
    {
        if (meta & (1 << i))
        {
            result[i] = 1.0f;
        }
    }

    return result;
}

void ElectricLamp::onInteract(LocalWorld &world, Player &player, glm::ivec3 pos, Side side, const RGBABytes &collisionKey)
{
    if (player.isHoldingScrewdriver())
    {
        uint8_t meta = *world.getBlockMeta(pos);
        uint8_t newColor = ((meta & 7) % 7) + 1;
        world.setBlockMeta(pos, (meta & ~7) | newColor);
        return;
    }

    SpriteBlock::onInteract(world, player, pos, side, collisionKey);
}