#ifndef OS_CORE_H
#define OS_CORE_H

typedef U32 OS_AccessFlags;
enum {
  OS_AccessFlag_Read      = (1<<0),
  OS_AccessFlag_Write     = (1<<1),
  OS_AccessFlag_Execute   = (1<<2),
  OS_AccessFlag_CreateNew = (1<<3),
  OS_AccessFlag_All       = 0xFFFFFFFF,
};

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

typedef enum OS_ErrorCode 
{
  OS_ErrorCode_Null,
  OS_ErrorCode_COUNT
} OS_ErrorCode;

typedef struct OS_Error OS_Error;
struct OS_Error {
  OS_Error *next;
  OS_ErrorCode code;  
};

typedef struct OS_ErrorList OS_ErrorList;
struct OS_ErrorList {
  OS_Error *first;
  OS_Error *last;
  U64 count;
};

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

typedef U64 OS_Timestamp;

typedef struct OS_FileAttributes OS_FileAttributes;
struct OS_FileAttributes
{
  U64 size;
  OS_Timestamp last_modified;
};

////////////////////////////////
//~ Helpers
root_function B32 OS_handle_match(OS_Handle a, OS_Handle b);

////////////////////////////////
//~ @os_per_backend Memory

root_function U64   OS_page_size(void);
root_function void* OS_reserve(U64 size);
root_function void  OS_release(void *ptr, U64 size);
root_function void  OS_commit(void *ptr, U64 size);
root_function void  OS_decommit(void *ptr, U64 size);
root_function void  OS_set_memory_access_flags(void *ptr, U64 size, OS_AccessFlags flags);

////////////////////////////////
//~ Thread and process types

typedef void OS_Thread_Function(void *params); //  void function pointer ?

root_function OS_InitReceipt OS_init(void);
root_function void  OS_thread_context_set(void *ptr);
root_function void* OS_thread_context_get(void);

////////////////////////////////
//~ @os_per_backend File System
root_function OS_Handle OS_file_open(OS_AccessFlags access_flags, String8 path);
root_function void      OS_file_close(OS_Handle file);
root_function String8   OS_file_read(Arena *arena, OS_Handle file, U64 min, U64 max);
// We supply whatever we want to write as a String8List, 
// so we can pull data from different places with no intermediate buffer.
root_function void      OS_file_write(Arena *arena, OS_Handle file, U64 off, 
                                      String8List data, OS_ErrorList *out_errors);
root_function OS_FileAttributes OS_attributes_from_file(OS_Handle file);

///////////////////////////////
//~ @os_per_backend Numerical value to string conversion
root_function String8List OS_to_string_list_F64(Arena *arena, F64 *values, U32 values_size, String8 format);

#endif /* OS_CORE_H */
