#ifndef CHUNK_HANDLE_HPP_
#define CHUNK_HANDLE_HPP_

#include <memory>

#include <Chunk/Chunk.hpp>

class World;

/**
 * @brief A smart pointer which retains a chunk.
 * 
 * This smart pointer wraps a `Chunk`, and each created instance of this handle
 * adds to the chunk's "retain count". When a `ChunkHandle` is destroyed, the retain
 * count goes down. This guarantees that if a ChunkHandle exists, the chunk will not
 * be unloaded.
 * 
 * Note that chunk handles are only safe in the main thread. Do not use them from async
 * tasks.
 */
class ChunkHandle
{
private:
    World &world;
    std::shared_ptr<Chunk> chunk;

public:
    /**
     * @brief Construct a chunk handle.
     * 
     * This constructor **does not** increment the retain counter.
     * 
     * @param world The world.
     * @param chunk The chunk.
     */
    ChunkHandle(World &world, std::shared_ptr<Chunk> chunk);

    /**
     * @brief Copy a chunk handle.
     * 
     * This constructor incremenets the retain count of the chunk.
     */
    ChunkHandle(const ChunkHandle &other);

    /**
     * @brief Decrements the retain count of the wrapped chunk.
     */
    ~ChunkHandle();

    /**
     * @brief Dereferences the chunk.
     */
    Chunk& operator*();

    /**
     * @brief Dereferences the chunk.
     */
    Chunk* operator->() const;

    /**
     * @brief Get the wrapped pointer.
     */
    operator std::shared_ptr<Chunk>();

    /**
     * @brief Assign a chunk handle to us.
     */
    ChunkHandle& operator=(const ChunkHandle &other);

    bool operator==(const ChunkHandle &other) const;
};

#endif