#ifndef ETEBASE_H
#define ETEBASE_H

/* Generated with cbindgen:0.14.3 */

/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
// +1 so we fake ceil it
#define ETEBASE_UTILS_FROM_BASE64_MAX_LEN(X) (((X) * 3U / 4U) + 1U)

// +2 so we fake ceil it + terminating null
#define ETEBASE_UTILS_TO_BASE64_MAX_LEN(X) (((X) * 4U / 3U) + 2U)

#define ETEBASE_UTILS_C_ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0]))


/**
 * The size of the private encryption key
 */
#define EtebasePRIVATE_KEY_SIZE 32

/**
 * The size of the salt added to the password to derive the symmetric encryption key
 */
#define EtebaseSALT_SIZE 16

/**
 * The access level to a collection
 */
enum EtebaseCollectionAccessLevel
#ifdef __cplusplus
  : uint32_t
#endif // __cplusplus
 {
  /**
   * Read only access
   */
  ETEBASE_COLLECTION_ACCESS_LEVEL_READ_ONLY,
  /**
   * Admin access
   */
  ETEBASE_COLLECTION_ACCESS_LEVEL_ADMIN,
  /**
   * Read and write access
   */
  ETEBASE_COLLECTION_ACCESS_LEVEL_READ_WRITE,
};
#ifndef __cplusplus
typedef uint32_t EtebaseCollectionAccessLevel;
#endif // __cplusplus

enum EtebaseErrorCode
#ifdef __cplusplus
  : uint32_t
#endif // __cplusplus
 {
  ETEBASE_ERROR_CODE_NO_ERROR,
  ETEBASE_ERROR_CODE_GENERIC,
  ETEBASE_ERROR_CODE_URL_PARSE,
  ETEBASE_ERROR_CODE_MSG_PACK,
  ETEBASE_ERROR_CODE_PROGRAMMING_ERROR,
  ETEBASE_ERROR_CODE_MISSING_CONTENT,
  ETEBASE_ERROR_CODE_PADDING,
  ETEBASE_ERROR_CODE_BASE64,
  ETEBASE_ERROR_CODE_ENCRYPTION,
  ETEBASE_ERROR_CODE_UNAUTHORIZED,
  ETEBASE_ERROR_CODE_CONFLICT,
  ETEBASE_ERROR_CODE_PERMISSION_DENIED,
  ETEBASE_ERROR_CODE_NOT_FOUND,
  ETEBASE_ERROR_CODE_CONNECTION,
  ETEBASE_ERROR_CODE_TEMPORARY_SERVER_ERROR,
  ETEBASE_ERROR_CODE_SERVER_ERROR,
  ETEBASE_ERROR_CODE_HTTP,
};
#ifndef __cplusplus
typedef uint32_t EtebaseErrorCode;
#endif // __cplusplus

/**
 * Dictates how much data to prefetch when passed to `EtebaseFetchOptions`
 */
enum EtebasePrefetchOption
#ifdef __cplusplus
  : uint32_t
#endif // __cplusplus
 {
  /**
   * Automatically decide based on the size of the data fetched
   */
  ETEBASE_PREFETCH_OPTION_AUTO,
  /**
   * Attempt to fetch a more lightweight (medium) amount of data
   */
  ETEBASE_PREFETCH_OPTION_MEDIUM,
};
#ifndef __cplusplus
typedef uint32_t EtebasePrefetchOption;
#endif // __cplusplus

/**
 * The main object for all user interactions and data manipulation, representing an authenticated
 * user account.
 */
typedef struct EtebaseAccount EtebaseAccount;

/**
 * The network client to use to interact with the Etebase server
 *
 * This is in charge of actually connecting to the server and making network requests.
 * If the `"networking"` crate feature is enabled, it uses an internal HTTP client based on
 * the `reqwest` crate. If the feature is not enabled, an external HTTP(S) client implementation
 * implementing the [`ClientImplementation`] trait needs to be supplied.
 */
typedef struct EtebaseClient EtebaseClient;

/**
 * A collection of items
 *
 * Like [`Item`]s, collections have two pieces of data associated with them:
 * * [metadata](ItemMetadata) - contains meta information like name and modification time
 * * Content - a buffer containing arbitrary binary data
 * They also have an immutable type and an associated sync token
 */
typedef struct EtebaseCollection EtebaseCollection;

/**
 * An manager for managing user invitations to collections
 */
typedef struct EtebaseCollectionInvitationManager EtebaseCollectionInvitationManager;

/**
 * The response of fetching a collection list
 */
typedef struct EtebaseCollectionListResponse_Collection EtebaseCollectionListResponse_Collection;

/**
 * A manager for managing collection operations like creation and fetching
 */
typedef struct EtebaseCollectionManager EtebaseCollectionManager;

/**
 * A member of a collection
 *
 * Obtained using [`CollectionManager::list`](crate::managers::CollectionManager::list)
 */
typedef struct EtebaseCollectionMember EtebaseCollectionMember;

/**
 * An manager for managing the members of a collection
 */
typedef struct EtebaseCollectionMemberManager EtebaseCollectionMemberManager;

/**
 * Configuration options for data fetching
 */
typedef struct EtebaseFetchOptions EtebaseFetchOptions;

typedef struct EtebaseFileSystemCache EtebaseFileSystemCache;

/**
 * Items belong to collections and are where data is stored
 *
 * Items have two pieces of data associated with them:
 * * [metadata](ItemMetadata) - contains meta information like name and modification time
 * * Content - a buffer containing arbitrary binary data.
 */
typedef struct EtebaseItem EtebaseItem;

/**
 * The response of fetching an item list
 */
typedef struct EtebaseItemListResponse_Item EtebaseItemListResponse_Item;

/**
 * A manager for managing item operations like creation and fetching
 */
typedef struct EtebaseItemManager EtebaseItemManager;

/**
 * Metadata of the item
 */
typedef struct EtebaseItemMetadata EtebaseItemMetadata;

/**
 * The response of fetching a list
 */
typedef struct EtebaseIteratorListResponse_CollectionMember EtebaseIteratorListResponse_CollectionMember;

/**
 * The response of fetching a list
 */
typedef struct EtebaseIteratorListResponse_Item EtebaseIteratorListResponse_Item;

/**
 * The response of fetching a list
 */
typedef struct EtebaseIteratorListResponse_SignedInvitation EtebaseIteratorListResponse_SignedInvitation;

/**
 * A collection for which the user lost access
 *
 * Deleted collections are marked using [`Collection::is_deleted`](crate::Collection::is_deleted).
 * However, when we just lose access
 * to a collection and it hasn't been deleted, we get this object.
 */
typedef struct EtebaseRemovedCollection EtebaseRemovedCollection;

/**
 * A signed invitation to join a collection
 */
typedef struct EtebaseSignedInvitation EtebaseSignedInvitation;

/**
 * A user object
 */
typedef struct EtebaseUser EtebaseUser;

/**
 * A user's public profile
 */
typedef struct EtebaseUserProfile EtebaseUserProfile;

typedef EtebaseCollectionListResponse_Collection EtebaseCollectionListResponse;

typedef EtebaseItemListResponse_Item EtebaseItemListResponse;

typedef EtebaseIteratorListResponse_Item EtebaseItemRevisionsListResponse;

typedef EtebaseIteratorListResponse_SignedInvitation EtebaseInvitationListResponse;

typedef EtebaseIteratorListResponse_CollectionMember EtebaseMemberListResponse;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

extern const uintptr_t ETEBASE_UTILS_PRETTY_FINGERPRINT_SIZE;

/**
 * Get the error code
 *
 * Call this immediately after a failed API call
 */
EtebaseErrorCode etebase_error_get_code(void);

/**
 * Get the error message
 *
 * Call this immediately after a failed API call
 */
const char *etebase_error_get_message(void);

/**
 * The URL of the main hosted server
 */
const char *etebase_get_default_server_url(void);

/**
 * Convert a Base64 URL encoded string to a buffer
 *
 * @param string the Base64 URL encoded string
 * @param[out] buf the output byte buffer
 * @param buf_maxlen the maximum number of bytes to be written to buf
 * @param[out] buf_len variable to store the buffer length in
 */
int32_t etebase_utils_from_base64(const char *string,
                                  void *buf,
                                  uintptr_t buf_maxlen,
                                  uintptr_t *buf_len);

/**
 * Convert a buffer to a Base64 URL encoded string
 *
 * @param bytes the buffer to convert
 * @param bytes_size the size of the input buffer
 * @param[out] out the output string
 * @param out_maxlen the maximum length of string to be written
 */
int32_t etebase_utils_to_base64(const void *bytes,
                                uintptr_t bytes_size,
                                char *out,
                                uintptr_t out_maxlen);

/**
 * Return a buffer filled with cryptographically random bytes
 *
 * @param[out] buf the output byte buffer
 * @param size the size of the returned buffer
 */
int32_t etebase_utils_randombytes(void *buf, uintptr_t size);

/**
 * Return a pretty formatted fingerprint of the content
 *
 * For example:
 * ```
 * 45680   71497   88570   93128
 * 19189   84243   25687   20837
 * 47924   46071   54113   18789
 * ```
 *
 * @param content the content to create a fingerprint for
 * @param content_size the size of the content buffer
 * @param[out] buf the output byte buffer
 */
int32_t etebase_utils_pretty_fingerprint(const void *content, uintptr_t content_size, char *buf);

EtebaseClient *etebase_client_new(const char *client_name, const char *server_url);

int32_t etebase_client_set_server_url(EtebaseClient *this_, const char *server_url);

/**
 * Returns 0 if client is pointing an etebase server, 1 if not, -1 on error
 *
 * @param client the object handle
 */
int32_t etebase_client_check_etebase_server(const EtebaseClient *client);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_client_destroy(EtebaseClient *this_);

/**
 * Return a new user instance
 *
 * Should be destroyed with `etebase_user_destroy`
 *
 * @param username the user's username
 * @param email the user's email
 */
EtebaseUser *etebase_user_new(const char *username, const char *email);

/**
 * Set the username
 *
 * @param this_ the object handle
 * @param username the user's username
 */
void etebase_user_set_username(EtebaseUser *this_, const char *username);

/**
 * Get the username
 *
 * @param this_ the object handle
 */
const char *etebase_user_get_username(const EtebaseUser *this_);

/**
 * Set the email address
 *
 * @param this_ the object handle
 * @param email the user's email address
 */
void etebase_user_set_email(EtebaseUser *this_, const char *email);

/**
 * Get the email address
 *
 * @param this_ the object handle
 */
const char *etebase_user_get_email(const EtebaseUser *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_user_destroy(EtebaseUser *this_);

/**
 * Login a user and return a handle to an `EtebaseAccount` object
 *
 * @param client the already setup `EtebaseClient` object
 * @param username the user's username. This is not the same as the user's email.
 * @param password the user's password
 */
EtebaseAccount *etebase_account_login(const EtebaseClient *client,
                                      const char *username,
                                      const char *password);

/**
 * Signup a new user account and return a handle to it
 *
 * @param client the already setup `EtebaseClient` object
 * @param user the already setup `EtebaseUser` object
 * @param password the password to signup with
 */
EtebaseAccount *etebase_account_signup(const EtebaseClient *client,
                                       const EtebaseUser *user,
                                       const char *password);

/**
 * Fetch a new auth token for the account and update the `EtebaseAccount` object with it
 *
 * @param this_ the object handle
 */
int32_t etebase_account_fetch_token(EtebaseAccount *this_);

/**
 * Fetch the link to the user dashboard of the account
 *
 * @param this_ the object handle
 */
char *etebase_account_fetch_dashboard_url(const EtebaseAccount *this_);

/**
 * Change the server URL for this account handle
 *
 * @param this_ the object handle
 * @param server_url the new server URL to be set
 */
int32_t etebase_account_force_server_url(EtebaseAccount *this_, const char *server_url);

/**
 * Change the user's login password
 *
 * @param this_ the object handle
 * @param password the new password to be set
 */
int32_t etebase_account_change_password(EtebaseAccount *this_, const char *password);

/**
 * Logout the user from the current session and invalidate the authentication token
 *
 * @param this_ the object handle
 */
int32_t etebase_account_logout(EtebaseAccount *this_);

/**
 * Return a `EtebaseCollectionManager` for creating, fetching and uploading collections
 *
 * @param this_ the object handle
 */
EtebaseCollectionManager *etebase_account_get_collection_manager(const EtebaseAccount *this_);

/**
 * Return a `EtebaseCollectionInvitationManager` for managing collection invitations
 *
 * @param this_ the object handle
 */
EtebaseCollectionInvitationManager *etebase_account_get_invitation_manager(const EtebaseAccount *this_);

/**
 * Save the account object to a string for restoring it later using `etebase_account_restore`
 *
 * @param this_ the object handle
 * @param encryption_key used to encrypt the returned account string to enhance security
 * @param encryption_key_size size of the encryption_key
 */
char *etebase_account_save(const EtebaseAccount *this_,
                           const void *encryption_key,
                           uintptr_t encryption_key_size);

/**
 * Restore and return the account object from the string obtained using `etebase_account_save`
 *
 * @param client the already setup `EtebaseClient` object
 * @param account_data_stored the stored account string
 * @param encryption_key the same encryption key passed to `etebase_account_save` while saving the account
 * @param encryption_key_size size of the encryption_key
 */
EtebaseAccount *etebase_account_restore(const EtebaseClient *client,
                                        const char *account_data_stored,
                                        const void *encryption_key,
                                        uintptr_t encryption_key_size);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_account_destroy(EtebaseAccount *this_);

/**
 * The uid of the removed collection
 *
 * @param this_ the object handle
 */
const char *etebase_removed_collection_get_uid(const EtebaseRemovedCollection *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_removed_collection_destroy(EtebaseRemovedCollection *this_);

/**
 * Sync token for the list response
 *
 * @param this_ the object handle
 */
const char *etebase_collection_list_response_get_stoken(const EtebaseCollectionListResponse *this_);

/**
 * List of collections included in the response
 *
 * @param this_ the object handle
 * @param[out] data the array to store the collections in
 */
int32_t etebase_collection_list_response_get_data(const EtebaseCollectionListResponse *this_,
                                                  const EtebaseCollection **data);

/**
 * The number of collections included in the response
 *
 * @param this_ the object handle
 */
uintptr_t etebase_collection_list_response_get_data_length(const EtebaseCollectionListResponse *this_);

/**
 * Indicates whether there are no more collections to fetch
 *
 * @param this_ the object handle
 */
bool etebase_collection_list_response_is_done(const EtebaseCollectionListResponse *this_);

/**
 * The list of collections to which the user lost access
 *
 * @param this_ the object handle
 * @param[out] data the array to store the collections in
 */
int32_t etebase_collection_list_response_get_removed_memberships(const EtebaseCollectionListResponse *this_,
                                                                 const EtebaseRemovedCollection **data);

/**
 * The number of collections to which the user lost access
 *
 * @param this_ the object handle
 */
uintptr_t etebase_collection_list_response_get_removed_memberships_length(const EtebaseCollectionListResponse *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_collection_list_response_destroy(EtebaseCollectionListResponse *this_);

/**
 * Sync token for the list response
 *
 * @param this_ the object handle
 */
const char *etebase_item_list_response_get_stoken(const EtebaseItemListResponse *this_);

/**
 * List of items included in the response
 *
 * @param this_ the object handle
 * @param[out] data the array to store the items in
 */
int32_t etebase_item_list_response_get_data(const EtebaseItemListResponse *this_,
                                            const EtebaseItem **data);

/**
 * The number of items included in the response
 *
 * @param this_ the object handle
 */
uintptr_t etebase_item_list_response_get_data_length(const EtebaseItemListResponse *this_);

/**
 * Indicates whether there are no more items to fetch
 *
 * @param this_ the object handle
 */
bool etebase_item_list_response_is_done(const EtebaseItemListResponse *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_item_list_response_destroy(EtebaseItemListResponse *this_);

/**
 * Iterator for the list response
 *
 * @param this_ the object handle
 */
const char *etebase_item_revisions_list_response_get_iterator(const EtebaseItemRevisionsListResponse *this_);

/**
 * List of item revisions included in the response
 *
 * @param this_ the object handle
 * @param[out] data the array to store the items in
 */
int32_t etebase_item_revisions_list_response_get_data(const EtebaseItemRevisionsListResponse *this_,
                                                      const EtebaseItem **data);

/**
 * The number of item revisions included in the response
 *
 * @param this_ the object handle
 */
uintptr_t etebase_item_revisions_list_response_get_data_length(const EtebaseItemRevisionsListResponse *this_);

/**
 * Indicates whether there is no more data to fetch
 *
 * @param this_ the object handle
 */
bool etebase_item_revisions_list_response_is_done(const EtebaseItemRevisionsListResponse *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_item_revisions_list_response_destroy(EtebaseItemRevisionsListResponse *this_);

/**
 * Return a new fetch options object
 *
 * Should be destroyed with `etebase_fetch_options_destroy`
 */
EtebaseFetchOptions *etebase_fetch_options_new(void);

/**
 * Limit the amount of items returned
 *
 * @param this_ the object handle
 * @param limit the limit to set
 */
void etebase_fetch_options_set_limit(EtebaseFetchOptions *this_, uintptr_t limit);

/**
 * How much data to prefetech
 *
 * @param this_ the object handle
 * @param prefetch the prefetch option to set
 */
void etebase_fetch_options_set_prefetch(EtebaseFetchOptions *this_, EtebasePrefetchOption prefetch);

/**
 * Toggle fetching the collection's item
 *
 * @param this_ the object handle
 * @param with_collection set whether to fetch the collection's item
 */
void etebase_fetch_options_set_with_collection(EtebaseFetchOptions *this_, bool with_collection);

/**
 * The current iterator to start from (when iterating lists)
 *
 * @param this_ the object handle
 * @param iterator the iterator to start from
 */
void etebase_fetch_options_set_iterator(EtebaseFetchOptions *this_, const char *iterator);

/**
 * The sync token to fetch with
 *
 * @param this_ the object handle
 * @param stoken the sync token to set
 */
void etebase_fetch_options_set_stoken(EtebaseFetchOptions *this_, const char *stoken);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_fetch_options_destroy(EtebaseFetchOptions *this_);

/**
 * Create a new metadata object
 *
 * Should be destroyed with `etebase_item_metadata_destroy`
 */
EtebaseItemMetadata *etebase_item_metadata_new(void);

/**
 * Set the item type
 *
 * @param this_ the object handle
 * @param item_type the type to be set
 */
void etebase_item_metadata_set_item_type(EtebaseItemMetadata *this_, const char *item_type);

/**
 * The item type
 *
 * @param this_ the object handle
 */
const char *etebase_item_metadata_get_item_type(const EtebaseItemMetadata *this_);

/**
 * Set the item name
 *
 * For example, you can set it to "Secret Note" or "todo.txt"
 *
 * @param this_ the object handle
 * @param name the name to be set
 */
void etebase_item_metadata_set_name(EtebaseItemMetadata *this_, const char *name);

/**
 * The item name
 *
 * @param this_ the object handle
 */
const char *etebase_item_metadata_get_name(const EtebaseItemMetadata *this_);

/**
 * Set the modification time of the item
 *
 * @param this_ the object handle
 * @param mtime the modification time in milliseconds since epoch
 */
void etebase_item_metadata_set_mtime(EtebaseItemMetadata *this_, const int64_t *mtime);

/**
 * Modification time of the item
 *
 * @param this_ the object handle
 */
const int64_t *etebase_item_metadata_get_mtime(const EtebaseItemMetadata *this_);

/**
 * Set a description for the item
 *
 * @param this_ the object handle
 * @param description the description to be set
 */
void etebase_item_metadata_set_description(EtebaseItemMetadata *this_, const char *description);

/**
 * The item description
 *
 * @param this_ the object handle
 */
const char *etebase_item_metadata_get_description(const EtebaseItemMetadata *this_);

/**
 * Set a color for the item
 *
 * @param this_ the object handle
 * @param color the color to be set in `#RRGGBB` or `#RRGGBBAA` format
 */
void etebase_item_metadata_set_color(EtebaseItemMetadata *this_, const char *color);

/**
 * The item color in `#RRGGBB` or `#RRGGBBAA` format
 *
 * @param this_ the object handle
 */
const char *etebase_item_metadata_get_color(const EtebaseItemMetadata *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_item_metadata_destroy(EtebaseItemMetadata *this_);

/**
 * Fetch a single collection from the server using its UID
 *
 * @param this_ the object handle
 * @param col_uid the UID of the collection to be fetched
 * @param fetch_options the `EtebaseFetchOptions` to fetch with
 */
EtebaseCollection *etebase_collection_manager_fetch(const EtebaseCollectionManager *this_,
                                                    const char *col_uid,
                                                    const EtebaseFetchOptions *fetch_options);

/**
 * Create a new collection
 *
 * Should be destroyed with `etebase_collection_destroy`
 *
 * @param this_ the object handle
 * @param collection_type the type of [Item]s stored in the collection
 * @param meta the [ItemMetadata] for the collection
 * @param content the collection's content as a byte array. This is unrelated to the [Item]s in the collection.
 * @param content_size the content size
 */
EtebaseCollection *etebase_collection_manager_create(const EtebaseCollectionManager *this_,
                                                     const char *collection_type,
                                                     const EtebaseItemMetadata *meta,
                                                     const void *content,
                                                     uintptr_t content_size);

/**
 * Create a new collection using raw metadata
 *
 * Unlike `etebase_collection_manager_create`, this receives the metadata as valid `EtebaseItemMetadata`-like struct encoded using `msgpack`.
 * This can be used to create collections with custom metadata types.
 *
 * Should be destroyed with `etebase_collection_destroy`
 *
 * @param this_ the object handle
 * @param collection_type the type of [Item]s stored in the collection
 * @param meta the metadata for the collection as a byte array
 * @param meta_size the metadata size
 * @param content the collection's content as a byte array. This is unrelated to the [Item]s in the collection.
 * @param content_size the content size
 */
EtebaseCollection *etebase_collection_manager_create_raw(const EtebaseCollectionManager *this_,
                                                         const char *collection_type,
                                                         const void *meta,
                                                         uintptr_t meta_size,
                                                         const void *content,
                                                         uintptr_t content_size);

/**
 * Return the item manager for the supplied collection
 *
 * @param this_ the object handle
 * @param col the collection for which the item manager is required
 */
EtebaseItemManager *etebase_collection_manager_get_item_manager(const EtebaseCollectionManager *this_,
                                                                const EtebaseCollection *col);

/**
 * Fetch all collections of a specific type from the server and return a list response
 *
 * @param this_ the object handle
 * @param collection_type the type of items stored in the collection
 * @param fetch_options the `EtebaseFetchOptions` to fetch with
 */
EtebaseCollectionListResponse *etebase_collection_manager_list(const EtebaseCollectionManager *this_,
                                                               const char *collection_type,
                                                               const EtebaseFetchOptions *fetch_options);

/**
 * Fetch all collections of the supplied types from the server and return a list response
 *
 * @param this_ the object handle
 * @param collection_types array of strings denoting the collection types
 * @param collection_types_size size of the collection_types array
 * @param fetch_options the `EtebaseFetchOptions` to fetch with
 */
EtebaseCollectionListResponse *etebase_collection_manager_list_multi(const EtebaseCollectionManager *this_,
                                                                     const char *const *collection_types,
                                                                     uintptr_t collection_types_size,
                                                                     const EtebaseFetchOptions *fetch_options);

/**
 * Upload a collection
 *
 * @param this_ the object handle
 * @param collection the collection object to be uploaded
 * @param fetch_options the `EtebaseFetchOptions` to upload with
 */
int32_t etebase_collection_manager_upload(const EtebaseCollectionManager *this_,
                                          const EtebaseCollection *collection,
                                          const EtebaseFetchOptions *fetch_options);

/**
 * Upload a collection using a transaction
 *
 * This call ensures that the collection hasn't changed since we last fetched it
 *
 * @param this_ the object handle
 * @param collection the collection object to be uploaded
 * @param fetch_options the `EtebaseFetchOptions` to upload with
 */
int32_t etebase_collection_manager_transaction(const EtebaseCollectionManager *this_,
                                               const EtebaseCollection *collection,
                                               const EtebaseFetchOptions *fetch_options);

/**
 * Load and return a cached collection object from a byte buffer
 *
 * @param this_ the object handle
 * @param cached the byte buffer holding the cached collection obtained using [cache_save]
 * @param cached_size size of the buffer
 */
EtebaseCollection *etebase_collection_manager_cache_load(const EtebaseCollectionManager *this_,
                                                         const void *cached,
                                                         uintptr_t cached_size);

/**
 * Save the collection object to a byte buffer for caching
 *
 * The collection can later be loaded using `etebase_collection_manager_cache_load`
 *
 * @param this_ the object handle
 * @param collection the collection object to be cached
 * @param[out] ret_size to hold the size of the returned buffer
 */
void *etebase_collection_manager_cache_save(const EtebaseCollectionManager *this_,
                                            const EtebaseCollection *collection,
                                            uintptr_t *ret_size);

/**
 * Save the collection object and its content to a byte buffer for caching
 *
 * The collection can later be loaded using `etebase_collection_manager_cache_load`
 *
 * @param this_ the object handle
 * @param collection the collection object to be cached
 * @param[out] ret_size to hold the size of the returned buffer
 */
void *etebase_collection_manager_cache_save_with_content(const EtebaseCollectionManager *this_,
                                                         const EtebaseCollection *collection,
                                                         uintptr_t *ret_size);

/**
 * Return the collection member manager for the supplied collection
 *
 * @param this_ the object handle
 * @param col the collection for which the manager is required
 */
EtebaseCollectionMemberManager *etebase_collection_manager_get_member_manager(const EtebaseCollectionManager *this_,
                                                                              const EtebaseCollection *col);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_collection_manager_destroy(EtebaseCollectionManager *this_);

/**
 * Fetch a single item from the server using its UID
 *
 * @param this_ the object handle
 * @param item_uid the UID of the item to be fetched
 * @param fetch_options the `EtebaseFetchOptions` to fetch with
 */
EtebaseItem *etebase_item_manager_fetch(const EtebaseItemManager *this_,
                                        const char *item_uid,
                                        const EtebaseFetchOptions *fetch_options);

/**
 * Create a new item
 *
 * Should be destroyed with `etebase_item_destroy`
 *
 * @param this_ the object handle
 * @param meta the [ItemMetadata] for the item
 * @param content the item's content as a byte array
 * @param content_size the content size
 */
EtebaseItem *etebase_item_manager_create(const EtebaseItemManager *this_,
                                         const EtebaseItemMetadata *meta,
                                         const void *content,
                                         uintptr_t content_size);

/**
 * Create a new item using raw metadata
 *
 * Unlike `etebase_item_manager_create`, this receives the metadata as valid `EtebaseItemMetadata`-like struct encoded using `msgpack`.
 * This can be used to create collections with custom metadata types.
 *
 * Should be destroyed with `etebase_item_destroy`
 *
 * @param this_ the object handle
 * @param meta the metadata for the item as a byte array
 * @param meta_size the metadata size
 * @param content the item's content as a byte array
 * @param content_size the content size
 */
EtebaseItem *etebase_item_manager_create_raw(const EtebaseItemManager *this_,
                                             const void *meta,
                                             uintptr_t meta_size,
                                             const void *content,
                                             uintptr_t content_size);

/**
 * Fetch all items of a collection and return a list response
 *
 * @param this_ the object handle
 * @param fetch_options the `EtebaseFetchOptions` to fetch with
 */
EtebaseItemListResponse *etebase_item_manager_list(const EtebaseItemManager *this_,
                                                   const EtebaseFetchOptions *fetch_options);

/**
 * Fetch and return a list response of items with each item as the revision
 *
 * @param this_ the object handle
 * @param item the item for which to fetch the revision history
 * @param fetch_options the `EtebaseFetchOptions` to fetch with
 */
EtebaseItemRevisionsListResponse *etebase_item_manager_item_revisions(const EtebaseItemManager *this_,
                                                                      const EtebaseItem *item,
                                                                      const EtebaseFetchOptions *fetch_options);

/**
 * Fetch the latest revision of the supplied items from the server and return a list response
 *
 * @param this_ the object handle
 * @param items the list of items to be fetched
 * @param items_size the number of items
 * @param fetch_options the `EtebaseFetchOptions` to fetch with
 */
EtebaseItemListResponse *etebase_item_manager_fetch_updates(const EtebaseItemManager *this_,
                                                            const EtebaseItem *const *items,
                                                            uintptr_t items_size,
                                                            const EtebaseFetchOptions *fetch_options);

/**
 * Fetch multiple Items using their UID
 *
 * See etebase_item_manager_fetch for fetching a single item
 *
 * @param this_ the object handle
 * @param items the list of item uids to be fetched
 * @param items_size the number of items
 * @param fetch_options the `EtebaseFetchOptions` to fetch with
 */
EtebaseItemListResponse *etebase_item_manager_fetch_multi(const EtebaseItemManager *this_,
                                                          const char *const *items,
                                                          uintptr_t items_size,
                                                          const EtebaseFetchOptions *fetch_options);

/**
 * Upload the supplied items to the server
 *
 * @param this_ the object handle
 * @param items the list of items to be uploaded
 * @param items_size the number of items
 * @param fetch_options the `EtebaseFetchOptions` to upload with
 */
int32_t etebase_item_manager_batch(const EtebaseItemManager *this_,
                                   const EtebaseItem *const *items,
                                   uintptr_t items_size,
                                   const EtebaseFetchOptions *fetch_options);

/**
 * Upload the supplied items to the server with a list of items as dependencies
 *
 * This will fail if the dependencies have changed remotely
 *
 * @param this_ the object handle
 * @param items the list of items to be uploaded
 * @param items_size the number of items
 * @param deps the list of items to be treated as dependencies
 * @param deps_size the number of dependencies
 * @param fetch_options the `EtebaseFetchOptions` to upload with
 */
int32_t etebase_item_manager_batch_deps(const EtebaseItemManager *this_,
                                        const EtebaseItem *const *items,
                                        uintptr_t items_size,
                                        const EtebaseItem *const *deps,
                                        uintptr_t deps_size,
                                        const EtebaseFetchOptions *fetch_options);

/**
 * Upload items using a transaction
 *
 * This call ensures that the items haven't changed since we last fetched them
 *
 * @param this_ the object handle
 * @param items the list of items to be uploaded
 * @param items_size the number of items
 * @param fetch_options the `EtebaseFetchOptions` to upload with
 */
int32_t etebase_item_manager_transaction(const EtebaseItemManager *this_,
                                         const EtebaseItem *const *items,
                                         uintptr_t items_size,
                                         const EtebaseFetchOptions *fetch_options);

/**
 * Upload items using a transaction with a list of items as dependencies
 *
 * @param this_ the object handle
 * @param items the list of items to be uploaded
 * @param items_size the number of items
 * @param deps the list of items to be treated as dependencies
 * @param deps_size the number of dependencies
 * @param fetch_options the `EtebaseFetchOptions` to upload with
 */
int32_t etebase_item_manager_transaction_deps(const EtebaseItemManager *this_,
                                              const EtebaseItem *const *items,
                                              uintptr_t items_size,
                                              const EtebaseItem *const *deps,
                                              uintptr_t deps_size,
                                              const EtebaseFetchOptions *fetch_options);

/**
 * Load and return a cached item from a byte buffer
 *
 * @param this_ the object handle
 * @param cached the byte buffer holding the cached item obtained using [cache_save]
 * @param cached_size size of the buffer
 */
EtebaseItem *etebase_item_manager_cache_load(const EtebaseItemManager *this_,
                                             const void *cached,
                                             uintptr_t cached_size);

/**
 * Save the item object to a byte buffer for caching
 *
 * The item can later be loaded using `etebase_item_manager_cache_load`
 *
 * @param this_ the object handle
 * @param item the item object to be cached
 * @param[out] ret_size to hold the size of the returned buffer
 */
void *etebase_item_manager_cache_save(const EtebaseItemManager *this_,
                                      const EtebaseItem *item,
                                      uintptr_t *ret_size);

/**
 * Save the item object and its content to a byte buffer for caching
 *
 * The item can later be loaded using `etebase_item_manager_cache_load`
 *
 * @param this_ the object handle
 * @param item the item object to be cached
 * @param[out] ret_size to hold the size of the returned buffer
 */
void *etebase_item_manager_cache_save_with_content(const EtebaseItemManager *this_,
                                                   const EtebaseItem *item,
                                                   uintptr_t *ret_size);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_item_manager_destroy(EtebaseItemManager *this_);

/**
 * Clone a collection object
 *
 * @param this_ the object handle
 */
EtebaseCollection *etebase_collection_clone(const EtebaseCollection *this_);

/**
 * Manually verify the integrity of the collection
 *
 * This is also done automatically by the API
 *
 * @param this_ the object handle
 */
bool etebase_collection_verify(const EtebaseCollection *this_);

/**
 * Set metadata for the collection object
 *
 * @param this_ the object handle
 * @param meta the metadata object to be set for the collection
 */
int32_t etebase_collection_set_meta(EtebaseCollection *this_, const EtebaseItemMetadata *meta);

/**
 * Return the metadata of the collection
 *
 * @param this_ the object handle
 */
EtebaseItemMetadata *etebase_collection_get_meta(const EtebaseCollection *this_);

/**
 * Set metadata for the collection object from a byte array
 *
 * @param this_ the object handle
 * @param meta the metadata for the collection. This needs to be a valid `EtebaseItemMetadata`-like struct encoded using `msgpack`.
 * @param meta_size the metadata size
 */
int32_t etebase_collection_set_meta_raw(EtebaseCollection *this_,
                                        const void *meta,
                                        uintptr_t meta_size);

/**
 * Write the metadata of the collection to a byte array and return its length
 *
 * @param this_ the object handle
 * @param[out] buf the output byte buffer
 * @param buf_size the maximum number of bytes to be written to buf
 */
intptr_t etebase_collection_get_meta_raw(const EtebaseCollection *this_,
                                         void *buf,
                                         uintptr_t buf_size);

/**
 * Set the content of the collection
 *
 * @param this_ the object handle
 * @param content the content of the collection as a byte array
 * @param content_size the content size
 */
int32_t etebase_collection_set_content(EtebaseCollection *this_,
                                       const void *content,
                                       uintptr_t content_size);

/**
 * Write the content of the collection to a byte array and return its length
 *
 * @param this_ the object handle
 * @param[out] buf the output byte buffer
 * @param buf_size the maximum number of bytes to be written to buf
 */
intptr_t etebase_collection_get_content(const EtebaseCollection *this_,
                                        void *buf,
                                        uintptr_t buf_size);

/**
 * Mark the collection as deleted
 *
 * The collection needs to be \ref uploaded `etebase_collection_manager_upload` for this to take effect
 *
 * @param this_ the object handle
 */
int32_t etebase_collection_delete(EtebaseCollection *this_);

/**
 * Check whether the collection is marked as deleted
 *
 * @param this_ the object handle
 */
bool etebase_collection_is_deleted(const EtebaseCollection *this_);

/**
 * The UID of the collection
 *
 * @param this_ the object handle
 */
const char *etebase_collection_get_uid(const EtebaseCollection *this_);

/**
 * The etag of the collection
 *
 * @param this_ the object handle
 */
const char *etebase_collection_get_etag(const EtebaseCollection *this_);

/**
 * The sync token for the collection
 *
 * The sync token reflects changes to the collection properties or its items on the server
 *
 * @param this_ the object handle
 */
const char *etebase_collection_get_stoken(const EtebaseCollection *this_);

/**
 * Return the collection as an item
 *
 * @param this_ the object handle
 */
EtebaseItem *etebase_collection_as_item(const EtebaseCollection *this_);

/**
 * The type of the collection
 *
 * @param this_ the object handle
 */
char *etebase_collection_get_collection_type(const EtebaseCollection *this_);

/**
 * Return the access level of the collection for the current user
 *
 * @param this_ the object handle
 */
EtebaseCollectionAccessLevel etebase_collection_get_access_level(const EtebaseCollection *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_collection_destroy(EtebaseCollection *this_);

/**
 * Clone an item object
 *
 * @param this_ the object handle
 */
EtebaseItem *etebase_item_clone(const EtebaseItem *this_);

/**
 * Manually verify the integrity of the item
 *
 * This is also done automatically by the API
 *
 * @param this_ the object handle
 */
bool etebase_item_verify(const EtebaseItem *this_);

/**
 * Set metadata for the item object
 *
 * @param this_ the object handle
 * @param meta the metadata object to be set for the item
 */
int32_t etebase_item_set_meta(EtebaseItem *this_, const EtebaseItemMetadata *meta);

/**
 * Return the metadata of the item
 *
 * @param this_ the object handle
 */
EtebaseItemMetadata *etebase_item_get_meta(const EtebaseItem *this_);

/**
 * Set metadata for the item object from a byte array
 *
 * @param this_ the object handle
 * @param meta the metadata for the item. This needs to be a valid `EtebaseItemMetadata`-like struct encoded using `msgpack`.
 * @param meta_size the metadata size
 */
int32_t etebase_item_set_meta_raw(EtebaseItem *this_,
                                  const void *meta,
                                  uintptr_t meta_size);

/**
 * Write the metadata of the item to a byte array and return its length
 *
 * @param this_ the object handle
 * @param[out] buf the output byte buffer
 * @param buf_size the maximum number of bytes to be written to buf
 */
intptr_t etebase_item_get_meta_raw(const EtebaseItem *this_, void *buf, uintptr_t buf_size);

/**
 * Set the content of the item
 *
 * @param this_ the object handle
 * @param content the content of the item as a byte array
 * @param content_size the content size
 */
int32_t etebase_item_set_content(EtebaseItem *this_, const void *content, uintptr_t content_size);

/**
 * Write the content of the item to a byte array and return its length
 *
 * @param this_ the object handle
 * @param[out] buf the output byte buffer
 * @param buf_size the maximum number of bytes to be written to buf
 */
intptr_t etebase_item_get_content(const EtebaseItem *this_, void *buf, uintptr_t buf_size);

/**
 * Mark the item as deleted
 *
 * The item needs to be \ref uploaded `etebase_item_manager_batch` for this to take effect
 *
 * @param this_ the object handle
 */
int32_t etebase_item_delete(EtebaseItem *this_);

/**
 * Check whether the item is marked as deleted
 *
 * @param this_ the object handle
 */
bool etebase_item_is_deleted(const EtebaseItem *this_);

/**
 * The UID of the item
 *
 * @param this_ the object handle
 */
const char *etebase_item_get_uid(const EtebaseItem *this_);

/**
 * The etag of the item
 *
 * @param this_ the object handle
 */
const char *etebase_item_get_etag(const EtebaseItem *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_item_destroy(EtebaseItem *this_);

/**
 * The user's identity public key
 *
 * This is used for identifying the user and safely sending them data (such as \ref invitations EtebaseSignedInvitation).
 */
const void *etebase_user_profile_get_pubkey(const EtebaseUserProfile *this_);

/**
 * The size of the user's identity public key
 *
 * @param this_ the object handle
 */
uintptr_t etebase_user_profile_get_pubkey_size(const EtebaseUserProfile *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_user_profile_destroy(EtebaseUserProfile *this_);

/**
 * Iterator for the list response
 *
 * @param this_ the object handle
 */
const char *etebase_invitation_list_response_get_iterator(const EtebaseInvitationListResponse *this_);

/**
 * List of invitations included in the response
 *
 * @param this_ the object handle
 * @param[out] data the array to store the items in
 */
int32_t etebase_invitation_list_response_get_data(const EtebaseInvitationListResponse *this_,
                                                  const EtebaseSignedInvitation **data);

/**
 * The number of invitations included in the response
 *
 * @param this_ the object handle
 */
uintptr_t etebase_invitation_list_response_get_data_length(const EtebaseInvitationListResponse *this_);

/**
 * Indicates whether there is no more data to fetch
 *
 * @param this_ the object handle
 */
bool etebase_invitation_list_response_is_done(const EtebaseInvitationListResponse *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_invitation_list_response_destroy(EtebaseInvitationListResponse *this_);

/**
 * List the incoming collection invitations for the account
 *
 * @param this_ the object handle
 * @param fetch_options the `EtebaseFetchOptions` to fetch with
 */
EtebaseInvitationListResponse *etebase_invitation_manager_list_incoming(const EtebaseCollectionInvitationManager *this_,
                                                                        const EtebaseFetchOptions *fetch_options);

/**
 * List the outgoing collection invitations for the account
 *
 * @param this_ the object handle
 * @param fetch_options the `EtebaseFetchOptions` to fetch with
 */
EtebaseInvitationListResponse *etebase_invitation_manager_list_outgoing(const EtebaseCollectionInvitationManager *this_,
                                                                        const EtebaseFetchOptions *fetch_options);

/**
 * Accept an invitation
 *
 * @param this_ the object handle
 * @param invitation the invitation to accept
 */
int32_t etebase_invitation_manager_accept(const EtebaseCollectionInvitationManager *this_,
                                          const EtebaseSignedInvitation *invitation);

/**
 * Reject an invitation
 *
 * @param this_ the object handle
 * @param invitation the invitation to reject
 */
int32_t etebase_invitation_manager_reject(const EtebaseCollectionInvitationManager *this_,
                                          const EtebaseSignedInvitation *invitation);

/**
 * Fetch and return a user's profile
 *
 * @param this_ the object handle
 * @param username the username of the user to fetch
 */
EtebaseUserProfile *etebase_invitation_manager_fetch_user_profile(const EtebaseCollectionInvitationManager *this_,
                                                                  const char *username);

/**
 * Invite a user to a collection
 *
 * @param this_ the object handle
 * @param collection the collection to invite to
 * @param username the username of the user to invite
 * @param pubkey the public key of the user to invite
 * @param pubkey_size the size of the public key
 * @param access_level the level of access to give to user
 */
int32_t etebase_invitation_manager_invite(const EtebaseCollectionInvitationManager *this_,
                                          const EtebaseCollection *collection,
                                          const char *username,
                                          const void *pubkey,
                                          uintptr_t pubkey_size,
                                          EtebaseCollectionAccessLevel access_level);

/**
 * Cancel an invitation (disinvite)
 *
 * @param this_ the object handle
 * @param invitation the invitation to cancel
 */
int32_t etebase_invitation_manager_disinvite(const EtebaseCollectionInvitationManager *this_,
                                             const EtebaseSignedInvitation *invitation);

/**
 * Our identity's public key
 *
 * This is the key users see when we send invitations.
 * Can be pretty printed with `etebase_utils_pretty_fingerprint`.
 *
 * @param this_ the object handle
 */
const void *etebase_invitation_manager_get_pubkey(const EtebaseCollectionInvitationManager *this_);

/**
 * The size of our identity's public key
 *
 * @param this_ the object handle
 */
uintptr_t etebase_invitation_manager_get_pubkey_size(const EtebaseCollectionInvitationManager *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_invitation_manager_destroy(EtebaseCollectionInvitationManager *this_);

/**
 * Clone the invitation object
 *
 * @param this_ the object handle
 */
EtebaseSignedInvitation *etebase_signed_invitation_clone(const EtebaseSignedInvitation *this_);

/**
 * The uid of the invitation
 *
 * @param this_ the object handle
 */
const char *etebase_signed_invitation_get_uid(const EtebaseSignedInvitation *this_);

/**
 * The username this invitation is for
 *
 * @param this_ the object handle
 */
const char *etebase_signed_invitation_get_username(const EtebaseSignedInvitation *this_);

/**
 * The uid of the collection this invitation is for
 *
 * @param this_ the object handle
 */
const char *etebase_signed_invitation_get_collection(const EtebaseSignedInvitation *this_);

/**
 * The access level offered in this invitation
 *
 * @param this_ the object handle
 */
EtebaseCollectionAccessLevel etebase_signed_invitation_get_access_level(const EtebaseSignedInvitation *this_);

/**
 * The username this invitation is from
 *
 * @param this_ the object handle
 */
const void *etebase_signed_invitation_get_from_username(const EtebaseSignedInvitation *this_);

/**
 * The public key of the inviting user
 *
 * @param this_ the object handle
 */
const void *etebase_signed_invitation_get_from_pubkey(const EtebaseSignedInvitation *this_);

/**
 * The size of the public key of the inviting user
 *
 * @param this_ the object handle
 */
uintptr_t etebase_signed_invitation_get_from_pubkey_size(const EtebaseSignedInvitation *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_signed_invitation_destroy(EtebaseSignedInvitation *this_);

/**
 * Clone the object
 *
 * @param this_ the object handle
 */
EtebaseCollectionMember *etebase_collection_member_clone(const EtebaseCollectionMember *this_);

/**
 * The username of a member
 *
 * @param this_ the object handle
 */
const char *etebase_collection_member_get_username(const EtebaseCollectionMember *this_);

/**
 * The access_level of the member
 *
 * @param this_ the object handle
 */
EtebaseCollectionAccessLevel etebase_collection_member_get_access_level(const EtebaseCollectionMember *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_collection_member_destroy(EtebaseCollectionMember *this_);

/**
 * Iterator for the list response
 *
 * @param this_ the object handle
 */
const char *etebase_member_list_response_get_iterator(const EtebaseMemberListResponse *this_);

/**
 * List of collection members included in the response
 *
 * @param this_ the object handle
 * @param[out] data the array to store the collection members in
 */
int32_t etebase_member_list_response_get_data(const EtebaseMemberListResponse *this_,
                                              const EtebaseCollectionMember **data);

/**
 * The number of collection members included in the response
 *
 * @param this_ the object handle
 */
uintptr_t etebase_member_list_response_get_data_length(const EtebaseMemberListResponse *this_);

/**
 * Indicates whether there is no more data to fetch
 *
 * @param this_ the object handle
 */
bool etebase_member_list_response_is_done(const EtebaseMemberListResponse *this_);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_member_list_response_destroy(EtebaseMemberListResponse *this_);

/**
 * List the members of a collection
 *
 * @param this_ the object handle
 * @param fetch_options the `EtebaseFetchOptions` to fetch with
 */
EtebaseMemberListResponse *etebase_collection_member_manager_list(const EtebaseCollectionMemberManager *this_,
                                                                  const EtebaseFetchOptions *fetch_options);

/**
 * Remove a member from the collection
 *
 * @param this_ the object handle
 * @param username the member's username
 */
int32_t etebase_collection_member_manager_remove(const EtebaseCollectionMemberManager *this_,
                                                 const char *username);

/**
 * Leave a collection the user is a member of
 *
 * @param this_ the object handle
 */
int32_t etebase_collection_member_manager_leave(const EtebaseCollectionMemberManager *this_);

/**
 * Modify the access level of a member
 *
 * @param this_ the object handle
 * @param username the member's username
 * @param access_level the new `EtebaseCollectionAccessLevel`
 */
int32_t etebase_collection_member_manager_modify_access_level(const EtebaseCollectionMemberManager *this_,
                                                              const char *username,
                                                              EtebaseCollectionAccessLevel access_level);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_collection_member_manager_destroy(EtebaseCollectionMemberManager *this_);

/**
 * Initialize a file system cache object
 *
 * Should be destroyed with `etebase_fs_cache_destroy`
 *
 * @param path the path to a directory to store cache in
 * @param username username of the user to cache data for
 */
EtebaseFileSystemCache *etebase_fs_cache_new(const char *path, const char *username);

/**
 * Clear all cache for the user
 *
 * @param this_ the object handle
 */
int32_t etebase_fs_cache_clear_user(const EtebaseFileSystemCache *this_);

/**
 * Save the user account
 *
 * Load it later using `etebase_fs_cache_load_account`
 *
 * @param this_ the object handle
 * @param etebase the account to save
 * @param encryption_key used to encrypt the saved account string to enhance security
 * @param encryption_key_size the size of the encryption_key
 */
int32_t etebase_fs_cache_save_account(const EtebaseFileSystemCache *this_,
                                      const EtebaseAccount *etebase,
                                      const void *encryption_key,
                                      uintptr_t encryption_key_size);

/**
 * Load the account object from cache
 *
 * @param this_ the object handle
 * @param client the already setup [Client] object
 * @param encryption_key the same encryption key passed to [Self::save_account] while saving the account
 * @param encryption_key_size the size of the encryption_key
 */
EtebaseAccount *etebase_fs_cache_load_account(const EtebaseFileSystemCache *this_,
                                              const EtebaseClient *client,
                                              const void *encryption_key,
                                              uintptr_t encryption_key_size);

/**
 * Save the collection list sync token
 *
 * @param this_ the object handle
 * @param stoken the sync token to be saved
 */
int32_t etebase_fs_cache_save_stoken(const EtebaseFileSystemCache *this_, const char *stoken);

/**
 * Load the collection list sync token from cache
 *
 * @param this_ the object handle
 */
char *etebase_fs_cache_load_stoken(const EtebaseFileSystemCache *this_);

/**
 * Save a collection's sync token
 *
 * @param this_ the object handle
 * @param col_uid the UID of the collection
 * @param stoken the sync token to be saved
 */
int32_t etebase_fs_cache_collection_save_stoken(const EtebaseFileSystemCache *this_,
                                                const char *col_uid,
                                                const char *stoken);

/**
 * Load the sync token for a collection
 *
 * @param this_ the object handle
 * @param col_uid the UID of the collection
 */
char *etebase_fs_cache_collection_load_stoken(const EtebaseFileSystemCache *this_,
                                              const char *col_uid);

/**
 * Save a collection to cache
 *
 * @param this_ the object handle
 * @param col_mgr collection manager for the account
 * @param col the collection to be saved
 */
int32_t etebase_fs_cache_collection_set(const EtebaseFileSystemCache *this_,
                                        const EtebaseCollectionManager *col_mgr,
                                        const EtebaseCollection *col);

/**
 * Remove a collection from cache
 *
 * @param this_ the object handle
 * @param col_mgr collection manager for the account
 * @param col_uid the UID of the collection to remove
 */
int32_t etebase_fs_cache_collection_unset(const EtebaseFileSystemCache *this_,
                                          const EtebaseCollectionManager *col_mgr,
                                          const char *col_uid);

/**
 * Load a collection from cache
 *
 * @param this_ the object handle
 * @param col_mgr collection manager for the account
 * @param col_uid the UID of the collection
 */
EtebaseCollection *etebase_fs_cache_collection_get(const EtebaseFileSystemCache *this_,
                                                   const EtebaseCollectionManager *col_mgr,
                                                   const char *col_uid);

/**
 * Save an item to cache
 *
 * @param this_ the object handle
 * @param item_mgr item manager for the parent collection
 * @param col_uid the UID of the parent collection
 * @param item the item to be saved
 */
int32_t etebase_fs_cache_item_set(const EtebaseFileSystemCache *this_,
                                  const EtebaseItemManager *item_mgr,
                                  const char *col_uid,
                                  const EtebaseItem *item);

/**
 * Remove an item from cache
 *
 * @param this_ the object handle
 * @param item_mgr item manager for the parent collection
 * @param col_uid the UID of the parent collection
 * @param item_uid the UID of the item
 */
int32_t etebase_fs_cache_item_unset(const EtebaseFileSystemCache *this_,
                                    const EtebaseItemManager *item_mgr,
                                    const char *col_uid,
                                    const char *item_uid);

/**
 * Load an item from cache
 *
 * @param this_ the object handle
 * @param item_mgr item manager for the parent collection
 * @param col_uid the UID of the parent collection
 * @param item_uid the UID of the item
 */
EtebaseItem *etebase_fs_cache_item_get(const EtebaseFileSystemCache *this_,
                                       const EtebaseItemManager *item_mgr,
                                       const char *col_uid,
                                       const char *item_uid);

/**
 * Destroy the object
 *
 * @param this_ the object handle
 */
void etebase_fs_cache_destroy(EtebaseFileSystemCache *this_);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

#endif /* ETEBASE_H */
