#if OS_WINDOWS

// This file is included in Arena.cpp, so we don't need to include headers here.

void platform_init (Arena* arena, s64 new_reserve) {
  s64 page_aligned_reserve_size = Align_To_Page_Size(new_reserve);
  
  void* address_start = 
    VirtualAlloc(nullptr, (u64)page_aligned_reserve_size, MEM_RESERVE, PAGE_READWRITE);
  
  // printf("Reserving range %p:%p (size: %llu)\n", address_start, (u8*)address_start + page_aligned_reserve_size, page_aligned_reserve_size);
  
  if (address_start == nullptr) {
    s32 error_code = GetLastError();
    printf("In Arena:platform_init, VirtualAlloc failed with code %d\n", error_code);
    return;
  }
  
  arena->memory_base = (u8*)address_start;
}

void extend_committed_pages (Arena* arena, u8* end) {
  s64 delta = end - arena->first_uncommitted_page;
  Assert(delta >= 0);
  
  s64 size = Align_To_Page_Size(delta);
  
  VirtualAlloc(arena->first_uncommitted_page, (u64)size, MEM_COMMIT, PAGE_READWRITE);
  // printf("Committing range %p:%p (size: %llu)\n", arena->first_uncommitted_page, (u8*)arena->first_uncommitted_page + size, size);
  
  // arena_lock_pages(arena, arena->first_uncommitted_page, size);
  arena->first_uncommitted_page += size;
}

void free_pages_down_to (Arena* arena, s64 pages_to_keep) {
  if (arena == nullptr) return;
  Assert(pages_to_keep >= 1); // Always keep one page because we bootstrap a lot.
  s64 bytes_to_keep = pages_to_keep * PLATFORM_MEMORY_PAGE_SIZE;
  if (bytes_to_keep > reserve_size(arena)) {
    Assert(false); // Break in debug builds, but release we just do nothing.
    return; // just do nothing here. Maybe we should assert?
  }
  
  u64 bytes_committed = (u64)(arena->first_uncommitted_page - arena->memory_base);
  if (bytes_to_keep > (s64)bytes_committed) {
    return; // nothing to free
  }
  
  u8* start_address = arena->memory_base + bytes_to_keep;
  u64 bytes_to_decommit = (u64)(arena->first_uncommitted_page - start_address);
  // arena_unlock_pages(arena, start_address, (s64)bytes_to_decommit);
  
  if (bytes_to_decommit) {
    VirtualFree(start_address, bytes_to_decommit, MEM_DECOMMIT);
    // printf("Freeing pages %p:%p (size: %llu)\n", start_address, (u8*)start_address + bytes_to_decommit, bytes_to_decommit);
  }
  
  arena->first_uncommitted_page = start_address;
}

void arena_delete (Arena* arena) {
  if (!is_valid(arena)) return;
  
#if BUILD_DEBUG
  { //default_allocator_free(arena->file_path.data);
    //default_allocator_free(arena->function_name.data);
    string_free_untracked(arena->label);
    remove_arena_from_in_use_list(arena);
  }
#endif
  
  // s64 size_tmp = reserve_size(arena);
  // printf("Releasing range %p:%p (size: %llu)\n", arena->memory_base, (u8*)arena->memory_base + size_tmp, size_tmp);
  bool arena_was_boostrapped = (arena->flags & Arena_Flags::Is_Bootstrapped) == Arena_Flags::Is_Bootstrapped;  
  
  VirtualFree(arena->memory_base, 0, MEM_RELEASE);

  if (!arena_was_boostrapped) {
    arena->memory_base = nullptr;
  }
}

#endif
