#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <savant.h>
#include <savutil.h>
#include <template.h>
#include <savantio.h>
#include <main.h>

int SavantVerbose = 0, SavantDebug = 0;

static void 
merge_docloc(int argc, char *argv[])
{
  /*  args = inpath1, inpath2, ..., inpathn, outpath */
  FILE *IN_DOCLOC_FILE, *OUT_DOCLOC_FILE;
  FILE *IN_DLOFF_FILE, *OUT_DLOFF_FILE;
  char buf[512];
  DB_UINT sizebuf[3];
  size_t bufread_big = 0;
  int i;
  DB_INT offset = 0, goffset = 0;

  OUT_DOCLOC_FILE = open_or_die(argv[argc-1], DOCLOC_FNAME, "w");
  OUT_DLOFF_FILE = open_or_die(argv[argc-1], DLOFF_FNAME, "w");

  for (i=1; i < (argc-1); i++) {
    /* open the new dbase */
    IN_DOCLOC_FILE = open_or_die(argv[i], DOCLOC_FNAME, "r");
    IN_DLOFF_FILE = open_or_die(argv[i], DLOFF_FNAME, "r");

    /* Catenate the DOCLOC file */
    bufread_big = fread_big((void *)buf, 1, 512, IN_DOCLOC_FILE);
    while (bufread_big != 0) {
      fwrite_big((void *)buf, 1, bufread_big, OUT_DOCLOC_FILE);
      bufread_big = fread_big((void *)buf, 1, 512, IN_DOCLOC_FILE);
    }      
    fflush(OUT_DOCLOC_FILE);

    /* Update the offset file */
    /* offset file = dl_offset, doc->body_start, and body_size bytes per doc */
    bufread_big = fread_big((void *)sizebuf, sizeof(DB_INT), 3, IN_DLOFF_FILE);
    while (bufread_big != 0) {
      offset = sizebuf[0] + goffset;   /* true offset = global + read */
      fwrite_big(&offset, sizeof(DB_INT), 1, OUT_DLOFF_FILE);
      fwrite_big(&(sizebuf[1]), sizeof(DB_INT), 2, OUT_DLOFF_FILE);
      bufread_big = fread_big((void *)sizebuf, sizeof(DB_INT), 3, IN_DLOFF_FILE);
    }
    goffset = ftell(OUT_DOCLOC_FILE);  /* update global offset */
    fflush(OUT_DLOFF_FILE);
    fclose(IN_DLOFF_FILE);
    fclose(IN_DOCLOC_FILE);
  } /* go on to next dbase directory */    
  fclose(OUT_DLOFF_FILE);
  fclose(OUT_DOCLOC_FILE);
}


static void 
merge_titles(int argc, char *argv[])
{
  /*  args = inpath1, inpath2, ..., inpathn, outpath */
  FILE *IN_TITLE_FILE, *OUT_TITLE_FILE;
  FILE *IN_TOFF_FILE, *OUT_TOFF_FILE;
  char buf[512];
  size_t bufread_big = 0;
  int i;
  DB_UINT offset = 0, goffset = 0;

  OUT_TITLE_FILE = open_or_die(argv[argc-1], TITLE_FNAME, "w");
  OUT_TOFF_FILE = open_or_die(argv[argc-1], TOFF_FNAME, "w");

  for (i=1; i < (argc-1); i++) {
    /* open the new dbase */
    IN_TITLE_FILE = open_or_die(argv[i], TITLE_FNAME, "r");
    IN_TOFF_FILE = open_or_die(argv[i], TOFF_FNAME, "r");

    /* Catenate the titles file */
    bufread_big = fread_big((void *)buf, 1, 512, IN_TITLE_FILE);
    while (bufread_big != 0) {
      fwrite_big((void *)buf, 1, bufread_big, OUT_TITLE_FILE);
      bufread_big = fread_big((void *)buf, 1, 512, IN_TITLE_FILE);
    }      
    fflush(OUT_TITLE_FILE);

    /* Update the offset file */
    bufread_big = fread_big((void *)buf, sizeof(DB_INT), 1, IN_TOFF_FILE);
    while (bufread_big != 0) {
      offset = *((DB_UINT *)buf) + goffset;   /* true offset = global + read */
      fwrite_big(&offset, sizeof(DB_INT), 1, OUT_TOFF_FILE);
      bufread_big = fread_big((void *)buf, sizeof(DB_INT), 1, IN_TOFF_FILE);
    }
    goffset = ftell(OUT_TITLE_FILE);  /* update global offset */
    fflush(OUT_TOFF_FILE);
    fclose(IN_TOFF_FILE);
    fclose(IN_TITLE_FILE);
  } /* go on to next dbase directory */    
  fclose(OUT_TOFF_FILE);
  fclose(OUT_TITLE_FILE);
}  

static void 
merge_biases(int argc, char *argv[])
{
  /*  args = inpath1, inpath2, ..., inpathn, outpath */
  FILE *IN_BIAS_FILE, *OUT_BIAS_FILE;
  char buf[512];
  size_t bufread_big = 0;
  int i;

  OUT_BIAS_FILE = open_or_die(argv[argc-1], BIAS_FNAME, "w");

  for (i=1; i < (argc-1); i++) {
    /* open the new dbase */
    IN_BIAS_FILE = open_or_die(argv[i], BIAS_FNAME, "r");

    /* Catenate the biases file */
    bufread_big = fread_big((void *)buf, 1, 512, IN_BIAS_FILE);
    while (bufread_big != 0) {
      fwrite_big((void *)buf, 1, bufread_big, OUT_BIAS_FILE);
      bufread_big = fread_big((void *)buf, 1, 512, IN_BIAS_FILE);
    }      
    fflush(OUT_BIAS_FILE);
    fclose(IN_BIAS_FILE);
  } /* go on to next dbase directory */    
  fclose(OUT_BIAS_FILE);
}  

static void 
merge_wmap(int argc, char *argv[])
{
  /*  args = inpath1, inpath2, ..., inpathn, outpath */
  FILE *IN_WMAP_FILE, *OUT_WMAP_FILE;
  DB_INT buf[3];
  size_t bufread_big = 0;
  int i;
  DB_INT global_docnum = 0, docnum = 0;

  OUT_WMAP_FILE = open_or_die(argv[argc-1], WMAP_FNAME, "w");

  for (i=1; i < (argc-1); i++) {
    /* open the new dbase */
    IN_WMAP_FILE = open_or_die(argv[i], WMAP_FNAME, "r");

    /* Catenate the WMAPs file */
    bufread_big = fread_big((void *)buf, sizeof(DB_INT), 2, IN_WMAP_FILE);
    while (bufread_big != 0) {
      docnum = buf[0] + global_docnum;
      fwrite_big(&docnum, sizeof(DB_INT), 1, OUT_WMAP_FILE);
      fwrite_big(&(buf[1]), sizeof(DB_INT), 1, OUT_WMAP_FILE);
      bufread_big = fread_big((void *)buf, sizeof(DB_INT), 2, IN_WMAP_FILE);
    }      
    fflush(OUT_WMAP_FILE);
    fclose(IN_WMAP_FILE);
    global_docnum = docnum + 1;
  } /* go on to next dbase directory */    
  fclose(OUT_WMAP_FILE);
}  

void 
main(int argc,
     char *argv[])
{
  if(argc < 3) {
    fprintf(stderr,"\nusage:\n");
    fprintf(stderr,"  ra-merge <source 1> ... <source N> <target> \n");
    fflush(stderr);
    exit(1);
  }
    
  merge_biases(argc, argv);
  merge_titles(argc, argv);
  merge_docloc(argc, argv);
  merge_wmap(argc, argv);

  merge_databases(argc, argv);
}
