#ifndef _ALIAS_FILE_SYSTEM_H_
#define _ALIAS_FILE_SYSTEM_H_

#include <alias/str.h>
#include <alias/data_structure/vector.h>
#include <alias/libuv.h>

struct alias_FileFindSynchronousResults {
  alias_Vector(alias_str) paths;
};

struct alias_Directory {
  alias_str path;
  void (*find_synchronous)(void *ud, alias_str pattern, alias_MemoryCB *mcb, struct alias_FileFindSynchronousResults *results);
  bool (*exists_synchronous)(void *ud, alias_str path);
  void (*read_all_synchronous)(void *ud, alias_str path, alias_MemoryCB *mcb, void **data_ptr, uint64_t *length_ptr);
  void *ud;
};

struct alias_DirectoryList {
  alias_Vector(struct alias_Directory) paths;
};

struct alias_FileWriter {
  int fd;
  uv_pipe_t pipe;
};



void alias_file_exists(alias_str path, void (*f)(void *ud, bool value), void *ud);

bool alias_file_exists_synchronous(alias_str path);

void alias_file_find(alias_str path, alias_str pattern, void (*error)(void *ud),
                     void (*found)(void *ud, alias_str found_path), void (*done)(void *ud), void *ud);

void alias_file_find_synchronous(alias_str path, alias_str pattern, alias_MemoryCB *mcb,
                                 struct alias_FileFindSynchronousResults *results);

void alias_file_read(alias_str path, void (*error)(void *ud),
                     void (*partial)(void *ud, const void *data, uint64_t length), void (*done)(void *ud), void *ud);

void alias_file_read_all(alias_str path, alias_MemoryCB *mcb, void (*error)(void *ud),
                         void (*done)(void *ud, const void *data, uint64_t length), void *ud);

bool alias_file_read_all_synchronous(alias_str path, alias_MemoryCB *mcb, void **data_ptr, uint64_t *length_ptr);

void alias_file_write(alias_str path, void (*error)(void *ud), void (*f)(void *ud, struct alias_FileWriter *writer),
                      void *ud);

bool alias_file_write_synchronous(alias_str path, struct alias_FileWriter *writer);


void alias_DirectoryList_init(struct alias_DirectoryList *dir);

void alias_DirectoryList_free(struct alias_DirectoryList *dir, alias_MemoryCB *mcb);

uint32_t alias_DirectoryList_add_path(struct alias_DirectoryList *dir, alias_MemoryCB *mcb, alias_str path);

uint32_t alias_DirectoryList_add_synchronous_interface(
    struct alias_DirectoryList *dir, alias_MemoryCB *mcb, bool (*exists_syncronous)(void *ud, alias_str path),
    void (*read_all_syncronous)(void *ud, alias_str path, void **data_ptr, uint64_t *length_ptr), void *ud);

void alias_DirectoryList_reset_before(struct alias_DirectoryList *dir, alias_MemoryCB *mcb, uint32_t index);

void alias_DirectoryList_find(struct alias_DirectoryList *dir, alias_str pattern, void (*error)(void *ud),
                     void (*found)(void *ud, alias_str found_path), void (*done)(void *ud), void *ud);

void alias_DirectoryList_read(const struct alias_DirectoryList *dir, alias_str path, void (*error)(void *ud),
                              void (*partial)(void *ud, const void *data, uint64_t length), void (*done)(void *ud),
                              void *ud);


void alias_FileWriter_write(struct alias_FileWriter *writer, const void *data, uint64_t length, void (*error)(void *ud),
                            void (*done)(void *ud), void *ud);

bool alias_FileWriter_write_synchronous(struct alias_FileWriter *writer, const void *data, uint64_t length);

void alias_FileWriter_close(struct alias_FileWriter *writer);

#endif