// vim:fileencoding=utf-8:foldmethod=marker

#ifndef FILE_H
#define FILE_H

#include "../../base/mem/allocator/mem_allocator.h"
#include "../../common/aliases/aliases.h"
#include "../../base/strings/str8/str8.h"

#ifdef WP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WP_PLATFORM_CPP

typedef struct WpFile WpFile;

typedef enum {
	WP_ACCESS_READ,                       // Equivalent to r
	WP_ACCESS_WRITE,                      // Equivalent to w
	WP_ACCESS_APPEND,                     // Equivalent to a
	WP_ACCESS_READ_EX,                    // Equivalent to r+
	WP_ACCESS_WRITE_EX,                   // Equivalent to w+
	WP_ACCESS_APPEND_EX,                  // Equivalent to a+
	WP_ACCESS_WRITE_FAIL_ON_EXIST,        // Equivalent to wx
	WP_ACCESS_WRITE_FAIL_ON_EXIST_EX,     // Equivalent to wx+

	COUNT_FILE_ACCESS_MODE,
} WpFileAccessMode;

typedef enum {
	WP_SEEK_START,
	WP_SEEK_CURRENT,
	WP_SEEK_END,

	COUNT_FILE_SEEK_ORIGIN,
} WpFileSeekOrigin;

// Return value should not be cached as it's not guaranteed to remain the same. Always call
// wpFileStdin to get the standard input stream
wp_extern WpFile *wpFileStdin(void);

// Return value should not be cached as it's not guaranteed to remain the same. Always call
// wpFileStdout to get the standard output stream
wp_extern WpFile *wpFileStdout(void);

// Return value should not be cached as it's not guaranteed to remain the same. Always call
// wpFileStderr to get the standard error stream
wp_extern WpFile *wpFileStderr(void);

WpFile *wpFileOpen(const WpAllocator *allocator, WpStr8RO *filepath, WpFileAccessMode mode);
i64     wpFileGetCurrentPosition(WpFile *file);
i64     wpFileSeek(WpFile *file, i64 offset, WpFileSeekOrigin origin);
i64     wpFileGetLength(WpFile *file);
u64     wpFileRead(void *dst_buf, WpFile *file, u64 byte_count);
i64     wpFileWrite(const void *src_buf, WpFile *file, u64 byte_count);
u64     wpFileReadStr8(WpStr8 *str, WpFile *file);
i64     wpFileWriteStr8(WpStr8RO *str, WpFile *file);
u64     wpFileReadArray(WpArray dst_buf, WpFile *file, u64 item_count);
i64     wpFileWriteArray(const WpArray src_buf, WpFile *file, u64 item_count);
i32     wpFileFlush(WpFile *file);
i32     wpFileClose(WpFile *file);
i32     wpFileRename(WpStr8RO *old_filepath, WpStr8RO *new_filepath);
i32     wpFileRemove(WpStr8RO *filepath);

wp_extern WpFile *_fileOpen(const WpAllocator *allocator, WpStr8RO *filepath, WpFileAccessMode mode);
wp_extern i64     _fileSeek(WpFile *file, i64 offset, WpFileSeekOrigin origin);
wp_extern u64     _fileRead(void *dst_buf, u64 byte_count, WpFile *file, u64 file_length);
wp_extern i64     _fileWrite(const void *src_buf, WpFile *file, u64 byte_count);
wp_extern i32     _fileFlush(WpFile *file);
wp_extern i32     _fileClose(WpFile *file);
wp_extern i32     _fileRename(WpStr8RO *old_filepath, WpStr8RO *new_filepath);
wp_extern i32     _fileRemove(WpStr8RO *filepath);

#ifdef WP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WP_PLATFORM_CPP

#endif // !FILE_H
