#include "witness.h"
#include "allocate.h"
#include "internal.h"

#include <stdio.h>

static void flush_buffer (chars *buffer) {
  fputc ('v', stdout);
  fwrite (BEGIN_STACK (*buffer), 1, SIZE_STACK (*buffer), stdout);
  fputc ('\n', stdout);
  CLEAR_STACK (*buffer);
}

static void print_int (kissat *solver, chars *buffer, int i) {
  char tmp[16];
  char *p = tmp + sizeof tmp;
  unsigned unsigned_i;
  if (i < 0)
    unsigned_i = 0u - (unsigned) i;
  else
    unsigned_i = (unsigned) i;
  do {
    *--p = '0' + (unsigned_i % 10);
    unsigned_i /= 10;
  } while (unsigned_i);
  if (i < 0)
    *--p = '-';
  *--p = ' ';
  const size_t tmp_len = (tmp + sizeof tmp) - p;
  size_t buf_len = SIZE_STACK (*buffer);
  if (buf_len + tmp_len > 77)
    flush_buffer (buffer);
  while (p != tmp + sizeof tmp)
    PUSH_STACK (*buffer, *p++);
}

void kissat_print_witness (kissat *solver, int max_var, bool partial) {
  chars buffer;
  INIT_STACK (buffer);
  for (int eidx = 1; eidx <= max_var; eidx++) {
    int tmp = kissat_value (solver, eidx);
    if (!tmp && !partial)
      tmp = eidx;
    if (tmp)
      print_int (solver, &buffer, tmp);
  }
  print_int (solver, &buffer, 0);
  assert (!EMPTY_STACK (buffer));
  flush_buffer (&buffer);
  RELEASE_STACK (buffer);
}
