// See Context_Base in jai, and TCTX in raddebugger: 

internal void Bootstrap_Main_Thread_Context () {
  // Timed_Block_Print_No_Context("Bootstrap_Main_Thread_Context");
  // 0. Setup general allocator
  default_allocator_Initialize_Allocation_Tracker();
  
  // 1. Setup arena free list
  // #note: the arena free list is disabled because I'm not convinced it's a good idea.
  // It would allow us to cache arenas to load address space very quickly (much faster than calling VirtualAlloc), but
  // it adds complexity and makes it difficult to know when you're doing something stupid, because memory is still writeable 
  // and readable after it's "freed" with `release_arena`. So for prototyping purposes, we just release the whole arena.
  
  // arena_free_list = (Arena_Free_List*)default_allocator_new(sizeof(Arena_Free_List), 64, true); // permanent allocation.
  // memset(arena_free_list, 0, sizeof(Arena_Free_List));
  // initialize_arena_free_list(default_allocator());
  
  // 1b. Setup arena in-use list:
  initialize_arenas_in_use_list();
  
  // 2. #NewContext Setup thread local context 
  ExpandableArena* arena_ex = bootstrap_expandable_arena(Arena_Reserve::Size_64M);
  
  thread_local_context = New<Thread_Context>(allocator(arena_ex));
  thread_local_context->temp           = bootstrap_expandable_arena(Arena_Reserve::Size_2M);
  thread_local_context->arena          = arena_ex;
  thread_local_context->allocator      = allocator(arena_ex);
  thread_local_context->thread_idx     = 0;
  thread_local_context->thread_name    = "Main Thread";
  thread_local_context->log_builder    = new_string_builder(Arena_Reserve::Size_64M);
  thread_local_context->string_builder = new_string_builder(Arena_Reserve::Size_2M);
  thread_local_context->error_arena    = bootstrap_arena(Arena_Reserve::Size_64M);

  default_logger_initialize();
  thread_local_context->logger = {default_logger_proc, &default_logger};
}

struct Push_Arena {
  Thread_Context* context;
  Allocator original_allocator;
  
  Push_Arena(ExpandableArena* arena_ex) {
    Assert(is_valid(arena_ex));
    context = thread_context();
    Assert(context != nullptr);
    original_allocator = context->allocator;
    context->allocator = allocator(arena_ex);
  }
  
  Push_Arena(Arena* arena) {
    Assert(is_valid(arena));
    context = thread_context();
    Assert(context != nullptr);
    original_allocator = context->allocator;
    context->allocator = allocator(arena);
  }
  
  ~Push_Arena() {
    context->allocator = original_allocator;
  }
};

force_inline void set_thread_context (Thread_Context* new_context) {
  thread_local_context = new_context;
}

// #Note: Both functions will free next arenas, we only worry about keeping memory in the first arena (typically 64MB).
void temp_reset_keeping_memory() {
  Thread_Context* context = thread_context();
  arena_reset(context->temp, false);
}

void temp_reset() { // alias: reset_temporary_storage.
  Thread_Context* context = thread_context();
  arena_reset(context->temp, true);
}
