#ifndef NPROOFS

#include "../src/file.h"

#include "test.h"
#include "testcnfs.h"

#ifdef KISSAT_COMPRESSED

#define MAX_COMPRESSED 10

static const char *compressions[MAX_COMPRESSED];
static unsigned size_compressions;

#define NEW_COMPRESSION(NAME, SUFFIX) \
  do { \
    if (!tissat_found_##NAME) \
      break; \
    assert (size_compressions < MAX_COMPRESSED); \
    compressions[size_compressions++] = SUFFIX; \
  } while (0)

static void init_compression (void) {
  // clang-format off
  NEW_COMPRESSION (bzip2, ".bz2");
  NEW_COMPRESSION (gzip, ".gz");
  NEW_COMPRESSION (lzma, ".lzma");
  NEW_COMPRESSION (7z, ".7z");
  NEW_COMPRESSION (xz, ".xz");
  // clang-format on
}

static unsigned compressed;

#endif

static unsigned scheduled;

static void schedule_prove_job_with_option (int expected, const char *opt,
                                            const char *cnf,
                                            const char *name) {
  char cmd[256];
  if (!kissat_file_readable (cnf)) {
    tissat_warning ("Skipping unreadable '%s'", cnf);
    return;
  }

  bool veripb = tissat_found_veripb;

  const char *suffix = "";

#ifdef KISSAT_COMPRESSED
  // VeriPB proof tests use plain PBP files.
  bool compress = false;

  if (compress)
    suffix = compressions[compressed++ % size_compressions];
#endif
  char proof[96];
  sprintf (proof, "%s.proof%u%s", name, scheduled, suffix);

  const char *binary = (scheduled % 5) ? "" : "--no-binary ";
  sprintf (cmd, "%s%s%s %s", opt, binary, cnf, proof);
  tissat_job *job = tissat_schedule_application (expected, cmd);
  scheduled++;

  const bool veripb_parses_cnf =
      strcmp (name, "xor3") && strcmp (name, "xor4");
  if (veripb && veripb_parses_cnf) {
    sprintf (cmd, "veripb -u --cnf %s %s", cnf, proof);
    assert (strlen (cmd) < sizeof cmd);
    tissat_schedule_command (0, cmd, job);
  }
}

static void schedule_prove_job (int expected, const char *cnf,
                                const char *name) {
  if (tissat_big) {
    for (all_tissat_options (opt))
      schedule_prove_job_with_option (expected, opt, cnf, name);
  } else {
    const char *opt = tissat_next_option (scheduled);
    schedule_prove_job_with_option (expected, opt, cnf, name);
  }
}

void tissat_schedule_prove (void) {
#ifdef KISSAT_COMPRESSED
  init_compression ();
#endif
#define CNF(EXPECTED, NAME, BIG) \
  if (!BIG || tissat_big) \
    schedule_prove_job (EXPECTED, "../test/cnf/" #NAME ".cnf", #NAME);
  CNFS
#undef CNF
}

#else
int tissat_prove_do_avoid_warning;
#endif
