/* GNU Guix --- Functional package management for GNU
   Copyright © 2020 Maxime Devos <maxime.devos@student.kuleuven.be>

   This file is part of GNU Guix.

   GNU Guix is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or (at
   your option) any later version.

   GNU Guix is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>. */

/**
 * @author Maxime Devos
 *
 * @file
 * Save hash->hash mappings in the data store
 * API that can be used to store hash -> hash mappings on a GNUnet node.
 * It is backed by the data store.
 */

#ifndef GNUNET_REHASH_SERVICE_H
#define GNUNET_REHASH_SERVICE_H

#include <gnunet/gnunet_fs_service.h>
#include "rehash_types.h"

#ifdef __cplusplus
extern "C"
{
#if 0
}
#endif
#endif

/**
 * Context to control hash->hash searches.
 */
struct GNUNET_REHASH_QueryContext;
/**
 * Context to control hash->hash inserts.
 */
struct GNUNET_REHASH_StoreContext;

/* TODO: perhaps some monitoring
   and enumeration? */

/**
 * Handle to the rehash service.
 */
struct GNUNET_REHASH_Handle;

/**
 * Connect to the rehash service.
 *
 * @param cfg configuration to use
 * @return handle to use to access the service
 */
struct GNUNET_REHASH_Handle *
GNUNET_REHASH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);

/**
 * Disconnect from the rehash service.
 *
 * @param h handle to the rehash service
 */
void
GNUNET_REHASH_disconnect (struct GNUNET_REHASH_Handle *h);


/**
 * Callback to call when a hash->hash mapping has been inserted.
 *
 * @param cls closure
 */
typedef void
(*GNUNET_REHASH_StoreContinuation) (void *cls);

/**
 * Where has the hash->hash mapping been found?
 * More locations may be defined later.
 * TODO is this useful?
 */
enum GNUNET_REHASH_Origin
{
  GNUNET_REHASH_ORIGIN_DHT = 0,
  GNUNET_REHASH_ORIGIN_DATASTORE = 1,
};

/**
 * Callback to call when a hash->hash mapping has been found
 *
 * The found hash may have a bogus for its type.
 *
 * @param cls closure
 * @param exp when will this value expire
 * @param origin where has this mapping been found
 * @param out_length size of @a out_hash
 * @param out_hash hash found
 */
typedef void
(*GNUNET_REHASH_QueryContinuation) (void *cls,
                                    struct GNUNET_TIME_Absolute exp,
                                    enum GNUNET_REHASH_Origin origin,
                                    size_t out_length,
                                    const char *out_hash);

/**
 * Store an hash->hash mapping into the data store
 * (and DHT, anonymity permitting), to be shared with
 * other peers. If the entry is already present, the old
 * entry is considered faulty and is replaced with the
 * new mapping.
 *
 * TODO: memory cont? When may StoreContext be freed?
 * How?
 *
 * @param h handle to the rehash store
 * @param options anonymity, replication, ... options
 * @param in_type type of hash to query with
 * @param out_type type of hash to search for
 * @param input hash to search with
 * @param input_length length of @a input_hash
 * @param output hash to find
 * @param output_length length of @a output_hash
 * @param cont continuation to call when done
 * @param cont_cls closure for @a cont
 * @return handle to abort the request
 */
struct GNUNET_REHASH_StoreContext *
GNUNET_REHASH_store_start (struct GNUNET_REHASH_Handle *h,
		           const struct GNUNET_FS_BlockOptions *options,
                           enum GNUNET_REHASH_Hash_Type in_type,
                           enum GNUNET_REHASH_Hash_Type out_type,
                           const char *input,
                           size_t input_length,
                           const char *output,
                           size_t output_length,
                           GNUNET_REHASH_StoreContinuation cont,
                           void *cls);

/**
 * Search for hash->hash mappings.
 *
 * @param h handle to rehash service
 * @param options only the flag LOOPBACK_ONLY is supported
 * @param anonymity desired anonymity level
 * @param in_type type of hash to query with
 * @param out_type type of hash to search for
 * @param input hash to search with
 * @param input_length length of @a input_hash
 * @param cont continuation to call when something is found
 * @return handle to abort the request
 */
struct GNUNET_REHASH_QueryContext *
GNUNET_REHASH_query_start (struct GNUNET_REHASH_Handle *h,
                           enum GNUNET_FS_SearchOptions options,
                           uint32_t anonymity,
                           enum GNUNET_REHASH_Hash_Type in_type,
                           enum GNUNET_REHASH_Hash_Type out_type,
                           const char *input,
                           size_t input_length,
                           GNUNET_REHASH_QueryContinuation cont,
                           void *cls);

/**
 * Abort trying to store a hash->hash mapping.
 * TODO: memory
 *
 * @param c context of action to abort
 */
void
GNUNET_REHASH_store_abort (struct GNUNET_REHASH_StoreContext *c);

/**
 * Stop searching. TODO: memory
 *
 * @param c context of action to abort
 */
void
GNUNET_REHASH_query_abort (struct GNUNET_REHASH_QueryContext *c);

#if 0
{
#endif
#ifdef __cplusplus
}
#endif

#endif
