#include <Block/SpriteBlock/Dynamo/Dynamo.hpp>
#include <Block/SpriteBlock/SpriteBlock.hpp>
#include <BoundingBox/BoundingBox.hpp>
#include <Utilities/Utilities.hpp>
#include <Entity/PhysicsEntity/CameraEntity/Player/Player.hpp>
#include <World/LocalWorld/LocalWorld.hpp>
#include <memory>

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

    sprites.push_back(
        Sprite{
            {"dynamo/side", "dynamo/side", "dynamo/side", "dynamo/side", "dynamo/bottom", "dynamo/side"},
            {
                BoundingBox<int>{0, 0, 0, 8, 8, 2},
                BoundingBox<int>{3, 3, 2, 5, 5, 8},
                BoundingBox<int>{0, 3, 6, 3, 5, 8},
            },
            "state0",
        }
    );

    sprites.push_back(
        Sprite{
            {"dynamo/side", "dynamo/side", "dynamo/side", "dynamo/side", "dynamo/bottom", "dynamo/side"},
            {
                BoundingBox<int>{0, 0, 0, 8, 8, 2},
                BoundingBox<int>{3, 3, 2, 5, 5, 8},
                BoundingBox<int>{3, 5, 6, 5, 8, 8},
            },
            "state1",
        }
    );

    sprites.push_back(
        Sprite{
            {"dynamo/side", "dynamo/side", "dynamo/side", "dynamo/side", "dynamo/bottom", "dynamo/side"},
            {
                BoundingBox<int>{0, 0, 0, 8, 8, 2},
                BoundingBox<int>{3, 3, 2, 5, 5, 8},
                BoundingBox<int>{5, 3, 6, 8, 5, 8},
            },
            "state2",
        }
    );

    sprites.push_back(
        Sprite{
            {"dynamo/side", "dynamo/side", "dynamo/side", "dynamo/side", "dynamo/bottom", "dynamo/side"},
            {
                BoundingBox<int>{0, 0, 0, 8, 8, 2},
                BoundingBox<int>{3, 3, 2, 5, 5, 8},
                BoundingBox<int>{3, 0, 6, 5, 3, 8},
            },
            "state3",
        }
    );

    return sprites;
}

Dynamo::Dynamo(std::string name) : SpriteBlock(
    name,
    "Dynamo",
    60.0f,
    "dynamo/icon",
    makeSprites()
)
{
    withMetalSounds();
}

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

void Dynamo::onInteract(LocalWorld &world, Player &player, glm::ivec3 pos, Side side, const RGBABytes &collisionKey)
{
    std::shared_ptr<MDynamo> dynamo = std::dynamic_pointer_cast<MDynamo>(world.getMachine(pos));
    dynamo->recharge();

    world.setBlockMeta(pos, (*world.getBlockMeta(pos) + 1) & 3);
}