/*
  This file is part of Anastasis
  Copyright (C) 2020, 2021 Anastasis SARL

  Anastasis 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, or (at your option) any later version.

  Anastasis 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
  Anastasis; see the file COPYING.GPL.  If not, see <http://www.gnu.org/licenses/>
*/
/**
 * @file include/anastasis_redux.h
 * @brief anastasis reducer api
 * @author Christian Grothoff
 * @author Dominik Meister
 * @author Dennis Neufeld
 */
#ifndef ANASTASIS_REDUX_H
#define ANASTASIS_REDUX_H

#include <jansson.h>
#include "anastasis.h"
#include <taler/taler_mhd_lib.h>
#include <regex.h>


/**
 * Initialize reducer subsystem.
 *
 * @param ctx context to use for CURL requests.
 */
void
ANASTASIS_redux_init (struct GNUNET_CURL_Context *ctx);


/**
 * Terminate reducer subsystem.
 */
void
ANASTASIS_redux_done (void);


/**
 * Returns an initial ANASTASIS backup state.
 *
 * @return NULL on failure
 */
json_t *
ANASTASIS_backup_start (const struct GNUNET_CONFIGURATION_Handle *cfg);


/**
 * Returns an initial ANASTASIS recovery state.
 *
 * @return NULL on failure
 */
json_t *
ANASTASIS_recovery_start (const struct GNUNET_CONFIGURATION_Handle *cfg);


/**
 * Signature of the callback passed to #ANASTASIS_redux_action()
 *
 * @param cls closure
 * @param error error code, #TALER_EC_NONE if @a new_bs is the new successful state
 * @param new_state the new state of the operation (client should json_incref() to keep an alias)
 */
typedef void
(*ANASTASIS_ActionCallback)(void *cls,
                            enum TALER_ErrorCode error,
                            json_t *new_state);


/**
 * Handle to an ongoing action. Only valid until the #ANASTASIS_ActionCallback is invoked.
 */
struct ANASTASIS_ReduxAction;


/**
 * Operates on a state. The new state is returned by a callback
 * function.  This function can do network access to talk to Anastasis
 * service providers.
 *
 * @param state input state
 * @param action what action to perform
 * @param arguments data for the @a action
 * @param cb function to call with the result
 * @param cb_cls closure for @a cb
 * @return failure state or new state
 */
struct ANASTASIS_ReduxAction *
ANASTASIS_redux_action (const json_t *state,
                        const char *action,
                        const json_t *arguments,
                        ANASTASIS_ActionCallback cb,
                        void *cb_cls);


/**
 * Cancel ongoing redux action.
 *
 * @param ra action to cancel
 */
void
ANASTASIS_redux_action_cancel (struct ANASTASIS_ReduxAction *ra);


/**
 * Handle for a policy discovery operation.
 */
struct ANASTASIS_PolicyDiscovery;


/**
 * Function called on each discovered recovery policy.
 *
 * The client can then start a new policy discovery process, using the
 * smallest (also most recent) @a version received per @a provider_url
 * in the cursor to resume.  Note that in this case, the application
 * logic is responsible for de-duplication using @a hcpd, or it may show
 * policies again if they are at different providers under versions not
 * queried up to the cursor.
 *
 * @param cls closure
 * @param hcpd hash of the compressed policy document (unique per policy)
 * @param provider_url which provider claims to have this policy
 * @param version version of the policy at this provider
 * @param attribute_mask combination of optional identity attributes
 *           present in the state that was used to locate this version
 * @param server_time when did the provider receive the upload
 * @param secret_name name the user assigned to the backup
 * @param providers json array of providers with this policy
 */
typedef void
(*ANASTASIS_PolicyDiscoveryCallback)(void *cls,
                                     const struct GNUNET_HashCode *hcpd,
                                     const char *provider_url,
                                     uint32_t version,
                                     json_int_t attribute_mask,
                                     struct GNUNET_TIME_Timestamp server_time,
                                     const char *secret_name,
                                     const json_t *providers);


/**
 * Start requesting providers for available policies for the
 * recovery specified in @a state.
 *
 * @param state state to discover polices in
 * @param cursor array containing "provider_url", attribute "mask",
 *               and "max_version" values (max_version is exclusive).
 *               Used for incremental discovery, NULL is allowed
 *               to begin from the latest version(s).
 * @param cb function to call with results
 * @param cb_cls closure for @a cb
 * @return NULL on failure
 */
struct ANASTASIS_PolicyDiscovery *
ANASTASIS_policy_discovery_start (const json_t *state,
                                  const json_t *cursor,
                                  ANASTASIS_PolicyDiscoveryCallback cb,
                                  void *cb_cls);


/**
 * Add another provider to the list of providers to do discovery
 * on.
 *
 * @param[in,out] pd policy discovery to expand
 * @param provider_url the provider to add to the set of providers
 * @param provider_state configuration state for that provider
 */
void
ANASTASIS_policy_discovery_more (struct ANASTASIS_PolicyDiscovery *pd,
                                 const char *provider_url,
                                 json_t *provider_state);

/**
 * Stop policy discovery.
 *
 * @param[in] pd operation to stop
 */
void
ANASTASIS_policy_discovery_stop (struct ANASTASIS_PolicyDiscovery *pd);


/**
 * Compute a subset of @a master_id removing optional attributes
 * based on the bits set in @a mask.
 *
 * @param state reducer state (tells us which attributes are optional)
 * @param master_id set of identity attributes to mask
 * @param mask bitmask to apply
 * @return masked copy of the @a master_id
 */
json_t *
ANASTASIS_mask_id_data (const json_t *state,
                        const json_t *master_id,
                        json_int_t mask);

/**
 * Lookup @a salt of @a provider_url in @a state.
 *
 * @param state the state to inspect
 * @param provider_url provider to look into
 * @param[out] salt value to extract
 * @return #GNUNET_OK on success
 */
enum GNUNET_GenericReturnValue
ANASTASIS_reducer_lookup_salt (const json_t *state,
                               const char *provider_url,
                               struct ANASTASIS_CRYPTO_ProviderSaltP *salt);


#endif  /* _ANASTASIS_REDUX_H */
