f64 GetUnixTimestamp ();
s64 GetUnixTimestampNanoseconds ();

struct Condition_Variable;
struct Semaphore;
struct Mutex;
struct OS_Thread;
struct File {
  HANDLE handle;
};

// struct File_Contents {
//   File file = {};
//   ArrayView<u8> file_data = {};
//   bool read_success = false;
// };

enum class Wait_For_Result : s32 {
  SUCCESS = 0,
  TIMEOUT = 1,
  ERROR = 2 // can't use ERROR because of Windows.h *sigh*
};

internal void mutex_init (Mutex* mutex);
internal void mutex_destroy (Mutex* mutex);
internal void lock (Mutex* mutex);
internal void unlock (Mutex* mutex);

internal void semaphore_init (Semaphore* sem, s32 initial_value = 0);
internal void semaphore_destroy (Semaphore* sem);
internal void signal (Semaphore* sem);
internal Wait_For_Result wait_for (Semaphore* sem, s32 milliseconds = -1);

internal void condition_variable_init (Condition_Variable* cv);
internal void condition_variable_destroy (Condition_Variable* cv);
internal void wait (Condition_Variable* cv, Mutex* mutex, s32 wait_time_ms = -1);
internal void wake (Condition_Variable* cv);
internal void wake_all (Condition_Variable* cv);

typedef u32 OS_Error_Code;
internal string get_error_string (OS_Error_Code error_code);

internal bool file_is_valid (File file);
internal File file_open (string file_path, bool for_writing=false, bool keep_existing_content=false, bool log_errors=false);
internal void file_close (File* file);
internal bool file_read (File file, void* data, s64 bytes_to_read_count, s64* bytes_read_count=nullptr);
internal bool file_length (File file, s64* length);
internal bool file_length (string file_path, s64* length);
internal s64 file_current_position (File file);
internal bool file_set_position (File file, s64 position);
internal ArrayView<u8> read_entire_file (File file);
internal ArrayView<u8> read_entire_file (string file_path, bool log_errors=false);

// use to_byte_view to convert ArrayView<non-u8> to ArrayView<u8>
internal bool file_write (File* file, void* data, s64 length);
internal bool write_entire_file (string file_path, void* file_data, s64 count);
internal bool write_entire_file (string file_path, ArrayView<u8> file_data);

// file_write
// write_entire_file...

// #TODO #fs File System Operations
// file_move, file_delete

// #window_creation
typedef HWND Window_Type;
