const std = @import("std");
pub const c = @import("c.zig").c;

pub const PathInfo = extern struct {
    _type: PathType, // the path type
    size: u64, // the file size in bytes
    create_time: Time, // the time when the path was created
    modify_time: Time, // the last time the path was modified
    access_time: Time, // the last time the path was read
};

pub const PathType = enum(c_int) {
    pathtypeNone, //path does not exist
    pathtypeFile, //a normal file
    pathtypeDirectory, //a directory
    pathtypeOther,
};

pub const Time = i64;

pub const GlobFlags = packed struct(u32) {
    globCaseinsensitive: bool = false,
    pad0: u30 = 0,
    rsvd: bool = false,
};

pub const EnumerateDirectoryCallback = c.SDL_EnumerateDirectoryCallback;

pub const PropertiesID = u32;

pub const StorageInterface = extern struct {
    version: u32,
    close: ?*const anyopaque,
    ready: ?*const anyopaque,
    enumerate: ?*const anyopaque,
    info: ?*const anyopaque,
    read_file: ?*const anyopaque,
    write_file: ?*const anyopaque,
    mkdir: ?*const anyopaque,
    remove: ?*const anyopaque,
    rename: ?*const anyopaque,
    copy: ?*const anyopaque,
    space_remaining: ?*const anyopaque,
};

pub const Storage = opaque {
    pub inline fn closeStorage(storage: *Storage) bool {
        return c.SDL_CloseStorage(storage);
    }

    pub inline fn storageReady(storage: *Storage) bool {
        return c.SDL_StorageReady(storage);
    }

    pub inline fn getStorageFileSize(storage: *Storage, path: [*c]const u8, length: *u64) bool {
        return c.SDL_GetStorageFileSize(storage, path, @ptrCast(length));
    }

    pub inline fn readStorageFile(storage: *Storage, path: [*c]const u8, destination: ?*anyopaque, length: u64) bool {
        return c.SDL_ReadStorageFile(storage, path, destination, length);
    }

    pub inline fn writeStorageFile(storage: *Storage, path: [*c]const u8, source: ?*const anyopaque, length: u64) bool {
        return c.SDL_WriteStorageFile(storage, path, source, length);
    }

    pub inline fn createStorageDirectory(storage: *Storage, path: [*c]const u8) bool {
        return c.SDL_CreateStorageDirectory(storage, path);
    }

    pub inline fn enumerateStorageDirectory(storage: *Storage, path: [*c]const u8, callback: EnumerateDirectoryCallback, userdata: ?*anyopaque) bool {
        return c.SDL_EnumerateStorageDirectory(storage, path, callback, userdata);
    }

    pub inline fn removeStoragePath(storage: *Storage, path: [*c]const u8) bool {
        return c.SDL_RemoveStoragePath(storage, path);
    }

    pub inline fn renameStoragePath(storage: *Storage, oldpath: [*c]const u8, newpath: [*c]const u8) bool {
        return c.SDL_RenameStoragePath(storage, oldpath, newpath);
    }

    pub inline fn copyStorageFile(storage: *Storage, oldpath: [*c]const u8, newpath: [*c]const u8) bool {
        return c.SDL_CopyStorageFile(storage, oldpath, newpath);
    }

    pub inline fn getStoragePathInfo(storage: *Storage, path: [*c]const u8, info: ?*PathInfo) bool {
        return c.SDL_GetStoragePathInfo(storage, path, info);
    }

    pub inline fn getStorageSpaceRemaining(storage: *Storage) u64 {
        return c.SDL_GetStorageSpaceRemaining(storage);
    }

    pub inline fn globStorageDirectory(storage: *Storage, path: [*c]const u8, pattern: [*c]const u8, flags: GlobFlags, count: *c_int) [*c][*c]u8 {
        return c.SDL_GlobStorageDirectory(storage, path, pattern, @bitCast(flags), @ptrCast(count));
    }
};

pub inline fn openTitleStorage(override: [*c]const u8, props: PropertiesID) ?*Storage {
    return c.SDL_OpenTitleStorage(override, props);
}

pub inline fn openUserStorage(org: [*c]const u8, app: [*c]const u8, props: PropertiesID) ?*Storage {
    return c.SDL_OpenUserStorage(org, app, props);
}

pub inline fn openFileStorage(path: [*c]const u8) ?*Storage {
    return c.SDL_OpenFileStorage(path);
}

pub inline fn openStorage(iface: *const StorageInterface, userdata: ?*anyopaque) ?*Storage {
    return c.SDL_OpenStorage(@ptrCast(iface), userdata);
}
