#ifndef SEARCH_STATE_HEADER
#define SEARCH_STATE_HEADER

#include <stdint.h>
#include "../../include/rcore.h"
#include "../../math/sparse.amat.h"

/* persistent state for the score-based search loop, held across .Call()s by an
 * R external pointer so the tabu list (and, later, the score cache) live in C
 * instead of crossing the R/C boundary at every iteration. */
typedef struct {

  int nnodes;             /* number of nodes. */
  int *coords;            /* the current network as a sorted arc-coordinate set. */
  int narcs;              /* number of arcs in the current network. */
  uint64_t current_hash;  /* fingerprint of the current network. */
  double *cache;          /* the nnodes x nnodes score-delta cache (column-major). */
  int tabu_size;          /* length of the tabu ring. */
  uint64_t *tabu_hashes;  /* per-slot network fingerprints. */
  int *tabu_len;          /* per-slot arc counts (-1 for empty slots). */

} search_state;

/* R interface (registered in globals.c). */
SEXP search_state_create(SEXP nodes, SEXP tabu);
SEXP search_set_network(SEXP state, SEXP arcs, SEXP nodes);
SEXP search_hash(SEXP state, SEXP current);
SEXP tabu_search_step(SEXP state, SEXP arcs, SEXP nodes, SEXP current, SEXP hash,
    SEXP data, SEXP score, SEXP extra, SEXP reference, SEXP equivalence,
    SEXP decomposability, SEXP updated, SEXP whitelist, SEXP blacklist,
    SEXP nparents, SEXP maxp, SEXP baseline, SEXP debug);

/* the score cache fill and the tabu step, orchestrated together by tabu_search_step(). */
SEXP score_cache_fill(SEXP nodes, SEXP data, SEXP score, SEXP extra,
    SEXP reference, SEXP equivalence, SEXP decomposability, SEXP updated,
    SEXP state, SEXP blacklist, SEXP debug);
SEXP tabu_step(SEXP nodes, SEXP reference, SEXP whitelist, SEXP blacklist,
    SEXP state, SEXP current, SEXP baseline, SEXP nparents, SEXP maxp,
    SEXP debug);

/* C-level accessor, arc-coordinate hash and tabu-ring lookup. */
search_state *search_state_from_SEXP(SEXP state);
uint64_t coord_hash(int coord);
int tabu_match(search_state *st, int cur, uint64_t hash);

/* the shared arc-addability predicate (from tabu.c). */
bool is_addable(sparse_amat sam, int i, int j, double *np, double *mp,
    int *b, int nbl, int nnodes);

#endif
