/*======================================================================
 FILE: icalbdbset.h

 SPDX-FileCopyrightText: 2001, Critical Path

 SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0

======================================================================*/

#ifndef ICALBDBSET_H
#define ICALBDBSET_H

#include "libical_icalss_export.h"
#include "icalset.h"

#include <db.h>

typedef struct icalbdbset_impl icalbdbset;

enum icalbdbset_subdb_type
{
    ICALBDB_CALENDARS,
    ICALBDB_EVENTS,
    ICALBDB_TODOS,
    ICALBDB_REMINDERS
};
typedef enum icalbdbset_subdb_type icalbdbset_subdb_type;

/** sets up the db environment, should be done in parent thread.. */
LIBICAL_ICALSS_EXPORT int icalbdbset_init_dbenv(char *db_env_dir,
                                                void (*logDbFunc)(const DB_ENV *,
                                                                  const char *, const char *));

LIBICAL_ICALSS_EXPORT icalset *icalbdbset_init(icalset *set, const char *dsn, void *options);

LIBICAL_ICALSS_EXPORT int icalbdbset_cleanup(void);

LIBICAL_ICALSS_EXPORT void icalbdbset_checkpoint(void);

LIBICAL_ICALSS_EXPORT void icalbdbset_rmdbLog(void);

/** Creates a component handle.  flags allows caller to
   specify if database is internally a BTREE or HASH */
LIBICAL_ICALSS_EXPORT icalset *icalbdbset_new(const char *database_filename,
                                              icalbdbset_subdb_type subdb_type,
                                              int dbtype, u_int32_t flag);

LIBICAL_ICALSS_EXPORT DB *icalbdbset_bdb_open_secondary(DB *dbp,
                                                        const char *subdb,
                                                        const char *sindex,
                                                        int (*callback)(DB *db,
                                                                        const DBT *dbt1,
                                                                        const DBT *dbt2,
                                                                        DBT *dbt3),
                                                        int type);

LIBICAL_ICALSS_EXPORT char *icalbdbset_parse_data(DBT *dbt, char *(*pfunc)(const DBT *dbt));

LIBICAL_ICALSS_EXPORT void icalbdbset_free(icalset *set);

/* cursor operations */
LIBICAL_ICALSS_EXPORT int icalbdbset_acquire_cursor(DB *dbp, DB_TXN *tid, DBC **rdbcp);

LIBICAL_ICALSS_EXPORT int icalbdbset_cget(DBC *dbcp, DBT *key, DBT *data,
                                          u_int32_t access_method);

LIBICAL_ICALSS_EXPORT int icalbdbset_cput(DBC *dbcp, DBT *key, DBT *data,
                                          u_int32_t access_method);

LIBICAL_ICALSS_EXPORT int icalbdbset_get_first(DBC *dbcp, DBT *key, DBT *data);

LIBICAL_ICALSS_EXPORT int icalbdbset_get_next(DBC *dbcp, DBT *key, DBT *data);

LIBICAL_ICALSS_EXPORT int icalbdbset_get_last(DBC *dbcp, DBT *key, DBT *data);

LIBICAL_ICALSS_EXPORT int icalbdbset_get_key(DBC *dbcp, DBT *key, DBT *data);

LIBICAL_ICALSS_EXPORT int icalbdbset_delete(DB *dbp, DBT *key);

LIBICAL_ICALSS_EXPORT int icalbdbset_put(DB *dbp, DBT *key, DBT *data, u_int32_t access_method);

LIBICAL_ICALSS_EXPORT int icalbdbset_get(DB *dbp, DB_TXN *tid, DBT *key, DBT *data,
                                         u_int32_t flags);

LIBICAL_ICALSS_EXPORT const char *icalbdbset_path(icalset *set);

LIBICAL_ICALSS_EXPORT const char *icalbdbset_subdb(icalset *set);

/* Mark the set as changed, so it will be written to disk when it
   is freed. Commit writes to disk immediately. */
LIBICAL_ICALSS_EXPORT void icalbdbset_mark(icalset *set);

LIBICAL_ICALSS_EXPORT icalerrorenum icalbdbset_commit(icalset *set);

LIBICAL_ICALSS_EXPORT icalerrorenum icalbdbset_add_component(icalset *set, icalcomponent *child);

LIBICAL_ICALSS_EXPORT icalerrorenum icalbdbset_remove_component(icalset *set,
                                                                icalcomponent *child);

LIBICAL_ICALSS_EXPORT int icalbdbset_count_components(icalset *set, icalcomponent_kind kind);

/* Restrict the component returned by icalbdbset_first, _next to those
   that pass the gauge. _clear removes the gauge */
LIBICAL_ICALSS_EXPORT icalerrorenum icalbdbset_select(icalset *store, icalgauge *gauge);

LIBICAL_ICALSS_EXPORT void icalbdbset_clear(icalset *store);

/* Gets and searches for a component by uid */
LIBICAL_ICALSS_EXPORT icalcomponent *icalbdbset_fetch(icalset *set,
                                                      icalcomponent_kind kind, const char *uid);

LIBICAL_ICALSS_EXPORT int icalbdbset_has_uid(icalset *set, const char *uid);

LIBICAL_ICALSS_EXPORT icalcomponent *icalbdbset_fetch_match(icalset *set, icalcomponent *c);

LIBICAL_ICALSS_EXPORT icalerrorenum icalbdbset_modify(icalset *set, icalcomponent *old,
                                                      icalcomponent *newc);

/* cluster management functions */
LIBICAL_ICALSS_EXPORT icalerrorenum icalbdbset_set_cluster(icalset *set, icalcomponent *cluster);

LIBICAL_ICALSS_EXPORT icalerrorenum icalbdbset_free_cluster(icalset *set);

LIBICAL_ICALSS_EXPORT icalcomponent *icalbdbset_get_cluster(icalset *set);

/* Iterate through components. If a gauge has been defined, these
   will skip over components that do not pass the gauge */

LIBICAL_ICALSS_EXPORT icalcomponent *icalbdbset_get_current_component(icalset *set);

LIBICAL_ICALSS_EXPORT icalcomponent *icalbdbset_get_first_component(icalset *set);

LIBICAL_ICALSS_EXPORT icalcomponent *icalbdbset_get_next_component(icalset *set);

/* External iterator for thread safety */
LIBICAL_ICALSS_EXPORT icalsetiter icalbdbset_begin_component(icalset *set,
                                                             icalcomponent_kind kind,
                                                             icalgauge *gauge, const char *tzid);

LIBICAL_ICALSS_EXPORT icalcomponent *icalbdbset_form_a_matched_recurrence_component(icalsetiter *
                                                                                        itr);

LIBICAL_ICALSS_EXPORT icalcomponent *icalbdbsetiter_to_next(icalset *set, icalsetiter *i);

LIBICAL_ICALSS_EXPORT icalcomponent *icalbdbsetiter_to_prior(icalset *set, icalsetiter *i);

/* Return a reference to the internal component. You probably should
   not be using this. */

LIBICAL_ICALSS_EXPORT icalcomponent *icalbdbset_get_component(icalset *set);

LIBICAL_ICALSS_EXPORT DB_ENV *icalbdbset_get_env(void);

LIBICAL_ICALSS_EXPORT int icalbdbset_begin_transaction(DB_TXN *parent_id, DB_TXN **txnid);

LIBICAL_ICALSS_EXPORT int icalbdbset_commit_transaction(DB_TXN *txnid);

LIBICAL_ICALSS_EXPORT DB *icalbdbset_bdb_open(const char *path,
                                              const char *subdb,
                                              int type, int mode, u_int32_t flag);

typedef struct icalbdbset_options {
    icalbdbset_subdb_type subdb; /**< the subdatabase to open */
    int dbtype;                  /**< db_open type: DB_HASH | DB_BTREE */
    int mode;                    /**< file mode */
    u_int32_t flag;              /**< DB->set_flags(): DB_DUP | DB_DUPSORT */
    char *(*pfunc)(const DBT *dbt);
    /**< parsing function */
    int (*callback)(DB *db,
                    /**< callback for secondary db open */
                    const DBT *dbt1, const DBT *dbt2, DBT *dbt3);
} icalbdbset_options;

#endif /* !ICALBDBSET_H */
