#include <Block/SpriteBlock/MultiBlock/NuclearReactor/NuclearReactor.hpp>
#include <Controller/InventoryController/NuclearReactorController/NuclearReactorController.hpp>
#include <Entity/PhysicsEntity/CameraEntity/Player/Player.hpp>
#include <World/LocalWorld/LocalWorld.hpp>

NuclearReactor::NuclearReactor(std::string name) : MultiBlock(name, "Nuclear reactor", {"dormant", "reacting"})
{
    int u, v, z;
    
    // Add the roof and floor.
    for (u=-3; u<=3; u++)
    {
        for (v=0; v<=6; v++)
        {
            structure.add(u, v, -3, "main:leadCasing");
            structure.add(u, v, 3, "main:leadCasing");
        }
    }

    // Add the walls.
    for (z=-2; z<=2; z++)
    {
        // Create the left-right walls.
        for (v=0; v<=6; v++)
        {
            structure.add(-3, v, z, "main:leadCasing");
            structure.add(3, v, z, "main:leadCasing");
        }

        // Create the front and back walls; don't include the already-added left and right sections.
        for (u=-2; u<=2; u++)
        {
            structure.add(u, 6, z, "main:leadCasing");

            // Don't add the interface block itself.
            if (u != 0 || z != 0)
            {
                structure.add(u, 0, z, "main:leadCasing");
            }
        }
    }

    withMetalSounds();
}

void NuclearReactor::getHarvestedStacks(LocalWorld &world, glm::ivec3 pos, std::vector<ItemStack> &stacks)
{
    MultiBlock::getHarvestedStacks(world, pos, stacks);
    
    std::shared_ptr<IInventory> inv = std::dynamic_pointer_cast<IInventory>(world.getMachine(pos));
    if (inv != nullptr)
    {
        int i;
        for (i=0; i<inv->getNumSlots(); i++)
        {
            ItemStack stack = inv->getStackInSlot(i);
            if (!stack.isEmpty())
            {
                stacks.push_back(stack);
            }
        }
    }
}

void NuclearReactor::onInteract(LocalWorld &world, Player &player, glm::ivec3 pos, Side side, const RGBABytes &collisionKey)
{
    player.connectController<NuclearReactorController>("main:NuclearReactorController", world.getMachine(pos));
}

glm::vec3 NuclearReactor::getLightColor(uint8_t meta)
{
    if (meta & metaReacting)
    {
        return glm::vec3(0.1f, 0.5f, 1.0f);
    }
    else
    {
        return glm::vec3(0.0f);
    }
}

glm::ivec3 NuclearReactor::getLightOffset(uint8_t meta)
{
    return glm::ivec3(4) - 4 * Structure::getIntoVector(meta & 3);
}

Sound& NuclearReactor::getBackgroundSound(uint8_t meta)
{
    if (meta & metaMeltdown)
    {
        return Sound::meltdown;
    }

    if (meta & metaReacting)
    {
        return Sound::nuclearReactor;
    }

    return Sound::NONE;
}