#ifndef ENIGMA_PFFILE_SDL_H
#define ENIGMA_PFFILE_SDL_H

#include <SDL2/SDL.h>

#include_next <cstdio>
#include <vector>
#include <cstdarg>

#define fread sdl_fread
#define fopen sdl_fopen
#define freopen sdl_freopen
#define fseek sdl_fseek
#define fclose sdl_fclose
#define fgetc sdl_fgetc
#define fgets sdl_fgets
#define fputc sdl_fputc
#define feof sdl_feof
#define ftell sdl_ftell
#define fwrite sdl_fwrite

#ifdef FILE
#  undef FILE
#endif
#define FILE SDL_RWops

inline size_t sdl_fread(void* ptr, size_t size, size_t maxnum, SDL_RWops* context) { 
  return SDL_RWread(context, ptr, size, maxnum);
}

inline SDL_RWops* sdl_fopen(const char* fname, const char* mode) {
  return SDL_RWFromFile(fname, mode);
}

inline SDL_RWops* sdl_freopen(const char* fname, const char* mode, SDL_RWops* context) {
  return (SDL_RWclose(context) + SDL_RWFromFile(fname, mode));
}

inline Sint64 sdl_fseek(SDL_RWops* context, Sint64 offset, int whence) {
  return SDL_RWseek(context, offset, whence);
}

inline int sdl_fclose(SDL_RWops* context) {
  return SDL_RWclose(context);
}

inline int sdl_fgetc(SDL_RWops* context) {
 int c;
 SDL_RWread(context, &c, sizeof(char), 1);
 return c; 
}

inline char* sdl_fgets(char* str, int num, SDL_RWops* context) {
  if (!SDL_RWread(context, str, sizeof(char), num)) {
    return nullptr;
  }
  return str;
}

inline int sdl_fputc(int character, SDL_RWops* context) {
 return SDL_RWwrite(context, &character, sizeof(char), 1); 
}

inline int sdl_feof(SDL_RWops* context) {
  return !SDL_RWread(context, nullptr, sizeof(char), 1);
}

inline Sint64 sdl_ftell(SDL_RWops* context) {
  return SDL_RWtell(context);
}

inline size_t sdl_fwrite(const void *ptr, size_t size, size_t count, SDL_RWops* context) {
  return SDL_RWwrite(context, ptr, size, count);
}

inline int fprintf(SDL_RWops* context, const char* fmt, ...) {
  va_list args;
  va_start (args, fmt);
  std::vector<char> buf(vsnprintf(nullptr, 0, fmt, args));
  vsnprintf(buf.data(), buf.size(), fmt, args);
  va_end(args);
  return sdl_fwrite(buf.data(), sizeof(char), buf.size(), context);
}

#endif
