/*
 * This file is part of the Poliqarp suite.
 * 
 * Copyright (C) 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 <bp/ng/xml-ipi.h>

/**
 * @return a newly allocated string
 */
static inline char* xml_get_ces_attr(xml_reader *reader, const char *name)
{
   return xml_get_attr(reader, NULL, name);
}

int xml_parse_morph_ipi(xml_reader *reader, struct document *document, struct corpus *corpus)
{
   char *document_id = NULL;
   int rc;
   struct segment segment;
   bool has_segment = false;
   struct interp *interp = NULL;
   bool space = false;
   struct corpus_document *corpus_document = NULL;

   while ((rc = xml_read(reader)) == 1) {
      if (!xml_has_ns(reader, NULL))
         continue;
      if (xml_has_start_tag(reader)) {
         if (xml_has_tag(reader, "ns"))
            space = false;
         else if (xml_is_empty(reader))
            continue; /* no other empty tags are relevant */
         if (document_id == NULL) {
            /* Not inside a <chunkList> */
            if (xml_has_tag(reader, "chunkList")) {
               assert(corpus_document == NULL);
               corpus_document = corpus_start_document(corpus);
               document_id = xml_get_id(reader);
               if (document_id == NULL)
                  document_id = bp_strdup("");
               assert(document_id != NULL);
               document_collect_metadata(document, corpus_document, document_id);
            } else
              continue;
         }
         if (xml_has_tag(reader, "chunk")) {
            char *tp = xml_get_ces_attr(reader, "type");
            corpus_push_subdocument(corpus_document, tp);
            free(tp);
         } else if (xml_has_tag(reader, "tok")) {
            if (has_segment)
               bp_warning("nested <tok>s");
            else {
               segment_create(&segment, false);
               has_segment = true;
            }
         } else if (xml_has_tag(reader, "lex")) {
            if (interp != NULL)
               bp_warning("nested <lex>es");
            else if (!has_segment) {
               bp_warning("<lex> outside <tok>");
            } else {
               interp = interp_alloc();
               char *disamb_text = xml_get_ces_attr(reader, "disamb");
               if (disamb_text != NULL && disamb_text[0] == '1' && disamb_text[1] == '\0')
                  interp->disamb = true;
               free(disamb_text);
               segment_add_interp(&segment, interp, NULL);
            }
         } else if (xml_has_tag(reader, "orth")) {
            if (!has_segment)
               bp_warning("<orth> outside <tok>");
            else if (segment.orth != NULL)
               bp_warning("more than one <orth> for a <tok>");
            else {
               xml_node *node = xml_expand(reader);
               segment.orth = xml_node_as_string(node);
               segment.space = space;
               xml_normalize_space(segment.orth);
            }
         } else if (xml_has_tag(reader, "base")) {
            if (interp == NULL)
               bp_warning("<base> outside <lex>");
            else if (interp->base != NULL) {
               bp_warning("more than one <base> for an <lex>");
            } else {
               xml_node *node = xml_expand(reader);
               interp->base = xml_node_as_string(node);
               xml_normalize_space(interp->base);
            }
         } else if (xml_has_tag(reader, "ctag")) {
            if (interp == NULL)
               bp_warning("<ctag> outside <lex>");
            else if (interp->tag != NULL)
               bp_warning("more than one <ctag> for an <lex>");
            else {
               xml_node *node = xml_expand(reader);
               interp->tag = xml_node_as_string(node);
               xml_normalize_space(interp->base);
            }
         }
      } else if (xml_has_end_tag(reader)) {
         if (xml_has_tag(reader, "chunkList")) {
            corpus_end_document(corpus_document, true);
            corpus_document = NULL;
            free(document_id);
            document_id = NULL;
         } else if (xml_has_tag(reader, "chunk"))
            corpus_pop_subdocument(corpus_document);
         else if (xml_has_tag(reader, "lex"))
            interp = NULL;
         else if (xml_has_tag(reader, "tok")) {
            rc = corpus_add_segment(corpus_document, &segment);
            segment_destroy(&segment);
            if (rc != 0)
               break;
            has_segment = false;
            space = true;
         }
      }
      else
         continue;
   }
   if (rc != 0 && document_id != NULL) {
      corpus_end_document(corpus_document, false);
      corpus_document = NULL;
   }
   free(document_id);
   return -(rc != 0);
}

bool xml_has_ipi_root(xml_reader *reader)
{
   return xml_has_ns(reader, NULL) && xml_has_tag(reader, "cesAna");
}
