#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>

#include "dawg.h"

#ifndef TRUE
#define TRUE (0==0)
#define FALSE (!TRUE)
#endif

NODE *rootdawg;
INDEX nedges;

int print = FALSE;
static void
dawg_pr(NODE *dawg, INDEX node, int len, char *w1, char *w2)
{
  static char word[MAX_WORD_LEN];
  NODE *edge;

  //fprintf(stderr, "node = %ld  dawg @ %p\n", node, dawg);

  for (edge = (NODE *)&dawg[node]; ; edge++) {
  long c;
    c = *edge;           /* Don't rewrite this - its avoiding a MSC bug */
    c = c >> V_LETTER;
    c = c & M_LETTER;
    word[len] = (char)c;
    if ((*edge & M_END_OF_WORD) != 0) {
      word[len+1] = '\0';
//fprintf(stderr, "examine %s\n", word);
      if (strcmp(word, w1) == 0) print = TRUE;
      if (print) fprintf(stdout, "%s\n", word);
      if (strcmp(word, w2) == 0) print = FALSE;
    }
    c = *edge & M_NODE_POINTER;
    if ((*edge & M_NODE_POINTER) != 0)
	dawg_pr (dawg, c, len + 1, w1, w2);
    if ((*edge & M_END_OF_NODE) != 0) break; /* End of node */
  }
}

void
dawg_print_inclusive_range(NODE *dawg, INDEX node, char *w1, char *w2)
{
    //fprintf(stderr, "pdawg %s..%s\n", w1, w2);
    dawg_pr(dawg, node, 0, w1, w2);
}


static char *dawg_w(NODE *dawg, INDEX node, int len, int *count, int target)
{
  static char word[MAX_WORD_LEN];
  NODE *edge;

  for (edge = (NODE *)&dawg[node]; ; edge++) {
    long c;
    c = *edge;           /* Don't rewrite this - its avoiding a MSC bug */
    c = c >> V_LETTER;
    c = c & M_LETTER;
    word[len] = (char)c;
    if ((*edge & M_END_OF_WORD) != 0) {
      word[len+1] = '\0';
      (*count) += 1; // fprintf(stdout, "%s\n", word);
      if (*count == target) return(word);
    }
    c = *edge & M_NODE_POINTER;
    if ((*edge & M_NODE_POINTER) != 0) {
      char *w = dawg_w (dawg, c, len + 1, count, target);
      if (w) return w;
    }
    if ((*edge & M_END_OF_NODE) != 0) break; /* End of node */
  }
  return NULL;
}

char *wordno(NODE *dawg, int no) // 1..count(dawg) inclusive
{
  int i = 0;
  return dawg_w(dawg, ROOT_NODE, 0, &i, no);
}

void dump_dict(NODE *dawg, char *low, char *high)
{
    print = FALSE;
    dawg_print_inclusive_range(dawg, ROOT_NODE, low, high);
}

#define MAX 16
int main(int argc, char **argv)
{
  char line[1024], line2[1024];
  char fname[256], rfname[256], *topline;
  char w1[MAX], w2[MAX];
  int max;
  int rank = 0, size = 1;
  int row, col;
  int hi, lo;
  int word, words;
  int found;
  NODE *vnode;
  int ch;

  if (argc == 1) {
    max = 10;
  } else if (argc == 2) {
    max = *argv[1];
    if (isdigit(max)) max = max - '0'; else max = 4;
  } else {
    fprintf(stderr, "syntax: ws 7\n        (or any number 2-9)\n");
    exit(1);
  }

  sprintf(fname, "dawg.%0d", max);
  if (!dawg_init(fname, &rootdawg, &nedges)) {
    fprintf(stderr, "Cannot open %s\n", fname);
    exit(1);
  }

  for (;;) {
    char *s = fgets(line, 1024, stdin);
    if (s == NULL) break;
    s = strchr(line, '\n');
    if (s != NULL) *s = '\0';
    if (strncmp(line, "==> ", 4) == 0) {
      // get low, high
	strncpy(w1, line+4, MAX); w1[10] = '\0'; strncpy(w2, line+15, MAX); w2[10] = '\0';
      fprintf(stderr, "%s-%s: ", w1, w2);
      s = fgets(line2, 1024, stdin);
      if (s == NULL) break;
      s = strchr(line, '\n');
      if (s != NULL) *s = '\0';
      if (strncmp(line2, "Starting: ", 10) == 0) {
	  strncpy(w1, line2+10, MAX); w1[10] = '\0';
	fprintf(stderr, "%s to %s remaining\n", w1, w2);
        dump_dict(rootdawg, w1, w2);
      } else {
	fprintf(stderr, "done\n");
      }
    }
  }
  exit(0);
  return(0);
}
