#ifndef ITEM_ENTITY_HPP_
#define ITEM_ENTITY_HPP_

#include <Utilities/FixedPoint.hpp>
#include <chrono>
#include <optional>
#include <Entity/Entity.hpp>
#include <Entity/PhysicsEntity/PhysicsEntity.hpp>
#include <ItemStack/ItemStack.hpp>
#include <Utilities/Extern.hpp>
#include <BoundingBox/BoundingBox.hpp>

using namespace std::chrono_literals;

/**
 * @brief Represents the "item" entity: an item dropped in the world.
 */
class ItemEntity : public PhysicsEntity
{
private:
    ItemStack stack;
    std::chrono::steady_clock::time_point spawnTime;
    std::optional<wfvec3> lastUpdatePos;
    bool updateCheckNeeded = false;
    static constexpr std::chrono::steady_clock::duration despawnAfter = 300s;

public:
    /**
     * @brief Construct a new item entity.
     * 
     * @param world The world.
     * @param typeId The type ID.
     * @param id The entity ID.
     * @param stack The stack to hold.
     */
    ItemEntity(World &world, std::string typeId, uint64_t id);

    /**
     * @brief Construct the entity during spawn.
     * 
     * @param world The world.
     * @param id The entity ID.
     * @param pos The position.
     * @param vel The velocity.
     * @param stack The item stack.
     */
    ItemEntity(World &world, uint64_t id, wfvec3 pos, wfvec3 vel, ItemStack stack);

    virtual glm::vec3 getFrictionCoefficients() override;
    virtual BoundingBox<wfixed> getBoundingBox(wfvec3 pos) override;
    virtual void update() override;
    virtual void draw(GraphicsContext &context, WorldDisplay &display) override;
    virtual void onMessage(const void *msg, size_t size) override;
    virtual void serializeState(std::vector<uint8_t> &outBytes) override;
    virtual size_t deserializeState(const uint8_t *data, size_t size) override;
    virtual void onEnteringUnloadedChunk() override;
    virtual bool onCollision() override;
};

#endif