/*
 * This file is part of the Poliqarp suite.
 * 
 * Copyright (C) 2004-2009 by Instytut Podstaw Informatyki Polskiej
 * Akademii Nauk (IPI PAN; Institute of Computer Science, Polish
 * Academy of Sciences; cf. www.ipipan.waw.pl).  All rights reserved.
 * 
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file gpl.txt included in the packaging
 * of this file.  (See http://www.gnu.org/licenses/translations.html for
 * unofficial translations.)
 * 
 * A commercial license is available from IPI PAN (contact
 * Michal.Ciesiolka@ipipan.waw.pl or ipi@ipipan.waw.pl for more
 * information).  Licensees holding a valid commercial license from IPI
 * PAN may use this file in accordance with that license.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

#include <poliqarp-config.h>

#include <foostring/foostring.h>
#include "chunk-merger.h"
#include "foolog.h"

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

/* FIXME: handler errors properly */
bp_parser *chunk_parser_create(const char *base_name, bool incremental)
{
   bp_parser *base;
   chunk_parser *this;
   char *path;

   base = malloc(sizeof *base + sizeof *this);

   base->destroy = chunk_parser_destroy;
   base->stats = chunk_parser_stats;
   base->work = chunk_parser_work;
   base->merge = chunk_parser_merge;
   base->preprocess = chunk_parser_pre_process;
   base->postprocess = chunk_parser_post_process;
   base->num_errors = 0;
   base->incremental = incremental;

   this = (void *) (((char *) base) + sizeof *base);

   this->base_name = strdup(base_name);
   this->num_errors = 0;
   this->chunk = ((struct poliqarp_document) {
      0, 0, 0, 0});

   path = string_aformat("%s." CORPUS_MARKER ".chunk.image", base_name);
   this->chunk_stream = xfopen(path, true);
   free(path);
   return base;
}

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

void chunk_parser_destroy(struct bp_parser *base)
{
   chunk_parser *this = (void *) (((char *) base) + sizeof *base);

   free(this->base_name);
   fclose(this->chunk_stream);
   free(base);
}

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

void chunk_parser_stats(struct bp_parser *base)
{
}

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

int chunk_parser_pre_process(struct bp_parser *base)
{
   return 0;
}

int chunk_parser_post_process(struct bp_parser *base)
{
   return 0;
}

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

void
chunk_parser_work(bp_parser_env * env,
   struct bp_parser *base,
   const char *pathname, const char *target_dir, const char *target_file)
{
}

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

void
chunk_parser_merge(bp_parser_env * env,
   struct bp_parser *base,
   const char *pathname, const char *target_dir, const char *target_file)
{
   chunk_parser *this = (void *) (((char *) base) + sizeof *base);
   char *path;
   struct stat stat_buf;
   size_t num_meta, num_corpus;
   int status;

   path =
      string_aformat(".partial.%s." CORPUS_MARKER ".meta.image",
      this->base_name);
   status = stat(path, &stat_buf);
   free(path);
   if (status == 0) {
      num_meta = stat_buf.st_size / sizeof(struct poliqarp_binary_metadata);
   }
   else {
      foolog(MSG_FATAL, _("Cannot find partial meta file in %s"), target_dir);
      this->num_errors++;
      return;
   }

   path =
      string_aformat(".partial.%s." CORPUS_MARKER ".corpus.image",
      this->base_name);
   status = stat(path, &stat_buf);
   free(path);
   if (status == 0) {
      num_corpus = stat_buf.st_size / sizeof(struct poliqarp_binary_segment);
   }
   else {
      foolog(MSG_FATAL, _("Cannot find partial corpus file in %s"),
         target_dir);
      this->num_errors++;
      return;
   }

   this->chunk.meta_high += num_meta;
   this->chunk.corpus_high += num_corpus;
   fwrite(&this->chunk, sizeof this->chunk, 1, this->chunk_stream);
   this->chunk.meta_low += num_meta;
   this->chunk.corpus_low += num_corpus;
}

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