/* date = March 19th 2024 10:21 am */

#ifndef DRAW_H
#define DRAW_H

typedef struct D_InitReceipt D_InitReceipt;
struct D_InitReceipt
{
  U64 u64[1];
};


///////////////////////////////////////////////////
//~ "Generated" code.
#include "draw_meta.h"

// The drawing bucket contains whatever should be drawn for this frame.
// And we can have several buckets that we submit.
// Each bucket has a list of passes. Each pass has a set of batch groups, ie 
// a collection of the data that is supposed to be rendered  for that pass. We can have
// several render batches per pass.
typedef struct D_Bucket D_Bucket;
struct D_Bucket
{
  R_PassList passes;
  String8 bucket_name;
  U64 last_cmd_stack_gen;
  U64 current_stack_gen;
  D_DeclBucketStacks;
};

typedef struct D_State D_State;
struct D_State
{
  Arena *arena;
  R_Handle font_texture;
};


typedef struct D_BucketSelectionNode D_BucketSelectionNode;
struct D_BucketSelectionNode
{
  D_BucketSelectionNode *next;
  D_Bucket *bucket;
  Arena *arena;
};

typedef struct D_ThreadCtx D_ThreadCtx;
struct D_ThreadCtx
{
  Arena *arena;
  Arena *fallback_arena;
  D_Bucket fallback_bucket;
  D_BucketSelectionNode bucket_selection_fallback;
  D_BucketSelectionNode *bucket_selection_top;
  D_BucketSelectionNode *bucket_selection_free;
  D_DeclThreadStackTops;
};

typedef struct D_RectParams D_RectParams;
struct D_RectParams
{
  R_Handle albedo_texture;
  Rng2_F32 src_rect;
  Vec4_F32 color;
  F32 corner_radius;
  F32 softness;
  F32 border_thickness;
  F32 omit_texture;
};

///////////////////////////////////////////////////
//~ Draw  fwd declarations
root_function D_InitReceipt D_init(R_InitReceipt r_init_receipt, F_InitReceipt f_init_receipt);
root_function void D_ensure_thread_initialised(void);
root_function void D_frame_begin();
root_function void D_frame_end();

///////////////////////////////////////////////////
//~ Buckets
root_function Arena *D_active_arena();
root_function D_Bucket *D_bucket_make(Arena *arena);
root_function void D_bucket_concat_in_place(D_Bucket *to_push);
root_function void D_push_bucket(Arena *arena, D_Bucket *bucket);
root_function void D_pop_bucket(void);
#define D_BucketScope(arena, bucket) DeferLoop(D_push_bucket((arena), (bucket)), D_pop_bucket())
root_function D_Bucket *D_active_bucket(void);
root_function void D_submit(R_Handle window_r, D_Bucket *bucket);

///////////////////////////////////////////////////
//~ Pass helpers
root_function R_Pass *D_pass_from_bucket(Arena *arena, D_Bucket *bucket, R_PassKind kind);

///////////////////////////////////////////////////
//~ UI pass build commands

//- Rect 
root_function R_Rect2DInst *D_rect2D_(Rng2_F32 rect, D_RectParams *p);
#define D_rect2D(r, ...) D_rect2D_((r), &(D_RectParams){.color = {1, 1, 1, 1}, __VA_ARGS__})
//- Text 
root_function F32 D_text2D(Vec2_F32 pos, String8 string, Vec4_F32 color);

///////////////////////////////////////////////////
//~ Grid build commands


///////////////////////////////////////////////////
//~ Draw stacks. 
// The nodes are generated by metadesk code in Ryan's codebase, I will do it manually here first.
// TODO(anton): generate this.
root_function R_Tex2DSampleKind      D_push_tex2D_sample_kind(R_Tex2DSampleKind v);

#endif //DRAW_H
