#ifndef ASSET_CACHE_H
#define ASSET_CACHE_H

#include "sys.h"
#include "work.h"
#include "util.h"

struct work_startup_receipt;

enum asset_status {
    ASSET_STATUS_NONE,

    ASSET_STATUS_UNINITIALIZED,
    /* TODO: ASSET_STATUS_QUEUED? */
    ASSET_STATUS_LOADING,
    ASSET_STATUS_READY
};

struct asset {
    /* Managed via asset_cache_touch */
    u64 hash;
    struct string key;

    /* Managed via asset_cache_set_work */
    struct work_handle work;
    struct sync_flag work_ready_sf;

    /* Managed via asset_cache_mark_x functions */
    enum asset_status status;
    struct sync_flag asset_ready_sf;

    /* Accessed via asset_cache_get_data */
    void *store_data;
};

struct asset_cache_store {
    struct arena *arena;

    /* Internal */
    struct sys_rw_mutex *rw_mutex;
};

struct asset_cache_startup_receipt { i32 _; };
struct asset_cache_startup_receipt asset_cache_startup(struct work_startup_receipt *work_sr);

struct asset *asset_cache_touch(struct string key, u64 hash, b32 *is_first_touch);

void asset_cache_mark_loading(struct asset *asset);
void asset_cache_mark_ready(struct asset *asset, void *store_data);

void asset_cache_set_work(struct asset *asset, struct work_handle *handle);
void asset_cache_wait(struct asset *asset);

void *asset_cache_get_store_data(struct asset *asset);
struct asset_cache_store asset_cache_store_open(void);
void asset_cache_store_close(struct asset_cache_store *store);

u64 asset_cache_hash(struct string key);

#endif
