#ifndef CF_PLUGIN_TABLE_H
#define CF_PLUGIN_TABLE_H

#include <string.h>

#include "cf_step_abi.h"

#ifdef __cplusplus
#define CF_EXTERN_C extern "C"
#else
#define CF_EXTERN_C
#endif

typedef struct CfPluginStepEntry {
  const char* iri;
  const char* sig_hash;
  CfStepCallFn call;
  CfStepValidateFn validate;
} CfPluginStepEntry;

#define CF_STEP_ENTRY(iri, hash, call_fn, validate_fn) { (iri), (hash), (call_fn), (validate_fn) },
#define CF_STEP_IRI(iri, hash, call_fn, validate_fn) (iri),

#define CF_DEFINE_STEP_TABLE(STEP_LIST_MACRO) \
  static const CfPluginStepEntry kSteps[] = { STEP_LIST_MACRO(CF_STEP_ENTRY) }; \
  static const char* kStepIris[] = { STEP_LIST_MACRO(CF_STEP_IRI) }; \
  CF_EXTERN_C CF_EXPORT size_t cf_list_steps(const char*** out_step_iris) { \
    if (out_step_iris) { *out_step_iris = kStepIris; } \
    return sizeof(kSteps) / sizeof(kSteps[0]); \
  } \
  CF_EXTERN_C CF_EXPORT int cf_resolve_step(const char* step_iri, CfStepVTable* out) { \
    if (!step_iri || !out) return -1; \
    for (size_t i = 0; i < sizeof(kSteps) / sizeof(kSteps[0]); ++i) { \
      if (strcmp(step_iri, kSteps[i].iri) == 0) { \
        out->step_iri = kSteps[i].iri; \
        out->signature_hash = kSteps[i].sig_hash; \
        out->call = kSteps[i].call; \
        out->validate = kSteps[i].validate; \
        return 0; \
      } \
    } \
    return -1; \
  }

#endif
