#include "internal.hpp"

namespace CaDiCaL {

/*------------------------------------------------------------------------*/

struct NameVal { const char * name; int val; };

/*------------------------------------------------------------------------*/

// These are dummy configurations, which require additional code.

static NameVal default_config[1];       // With '-pedantic' just '[]' or
static NameVal plain_config[1];         // '[0]' gave a warning.

/*------------------------------------------------------------------------*/

// Here we have the pre-defined default configurations.

static NameVal sat_config[] = {
  { "elimreleff", 10 },
  { "stabilizeonly", 1 },
  { "subsumereleff", 60 },
};

static NameVal unsat_config[] = {
  { "stabilize", 0 },
  { "walk", 0 },
};

/*------------------------------------------------------------------------*/

#define CONFIGS \
 \
CONFIG(default,"set default advanced internal options") \
CONFIG(plain,"disable all internal preprocessing options") \
CONFIG(sat,"set internal options to target satisfiable instances") \
CONFIG(unsat,"set internal options to target unsatisfiable instances") \

static const char * configs [] = {
#define CONFIG(N,D) #N,
CONFIGS
#undef CONFIG
};

static size_t num_configs = sizeof configs / sizeof *configs;

/*------------------------------------------------------------------------*/

bool Config::has (const char * name) {
#define CONFIG(N,D) \
  if (!strcmp (name, #N)) return true;
  CONFIGS
#undef CONFIG
  return false;
}

bool Config::set (Options & opts, const char * name) {
  if (!strcmp (name, "default")) {
    opts.reset_default_values ();
    return true;
  }
  if (!strcmp (name, "plain")) {
    opts.disable_preprocessing ();
    return true;
  }
#define CONFIG(N,D) \
  do { \
    if (strcmp (name, #N)) break; \
    const NameVal * BEGIN = N ## _config; \
    const NameVal * END = BEGIN + sizeof N ##_config / sizeof (NameVal); \
    for (const NameVal * P = BEGIN; P != END; P++) { \
      assert (Options::has (P->name)); \
      opts.set (P->name, P->val); \
    } \
    return true; \
  } while (0);
  CONFIGS
#undef CONFIG
  return false;
}

/*------------------------------------------------------------------------*/

void Config::usage () {
#define CONFIG(N,D) \
  printf ("  %-14s " D "\n", "--" #N);
  CONFIGS
#undef CONFIG
}

/*------------------------------------------------------------------------*/

const char ** Config::begin () { return configs; }
const char ** Config::end () { return &configs[num_configs]; }

}
