/*
 * 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 "metadata.h"

struct poliqarp_meta_date parse_date(const char *text)
{
   char *ptr;
   struct poliqarp_meta_date result;

   /* FIXME: error checking? */
   result.year = result.month = result.day = 0;
   result.year = strtod(text, &ptr);
   if (*ptr == 0)
      return result;
   result.month = strtod(ptr + 1, &ptr);
   if (*ptr == 0)
      return result;
   result.day = strtod(ptr + 1, &ptr);
   return result;
}

void store_meta(struct header_parser *this,
   struct poliqarp_binary_metadata *meta)
{
   fwrite(meta, sizeof *meta, 1, this->meta_stream);
}

void pack_meta_single(struct poliqarp_binary_metadata *this, size_t key,
   size_t value)
{
   this->type = POLIQARP_METADATA_SINGLE;
   this->key = key;
   this->value_as.text = value;
}

void pack_meta_multi(struct poliqarp_binary_metadata *this, size_t key,
   size_t value)
{
   this->type = POLIQARP_METADATA_MULTI;
   this->key = key;
   this->value_as.text = value;
}

void pack_meta_date(struct poliqarp_binary_metadata *this, size_t key,
   const char *value)
{
   this->type = POLIQARP_METADATA_DATE;
   this->key = key;
   this->value_as.date = parse_date(value);
}

struct meta_item *meta_item_create(struct binary_pool_node *key_node,
   enum poliqarp_binary_metadata_type type, size_t num_paths,
   const char *const *path)
{
   struct meta_item *this;
   size_t i;

   this = malloc(sizeof *this);

   this->type = type;
   this->key_node = key_node;
   this->num_paths = num_paths;
   this->path = malloc(sizeof *this->path * num_paths);
   for (i = 0; i < num_paths; ++i)
      poliqarp_regexp_create(&this->path[i], path[i], REG_NOSUB, 0);
   this->def_path = NULL;
   this->values = this->valend = NULL;

   return this;
}

void meta_item_destroy(void *ptr)
{
   struct meta_item *this = ptr;
   size_t i;

   for (i = 0; i < this->num_paths; ++i)
      poliqarp_regexp_destroy(this->path + i);
   free(this->path);
   free(this);
}

int meta_item_compare_by_name(const void *p1, const void *p2)
{
   return strcmp(((struct meta_item *) p1)->key_node->data,
      (const char *) p2);
}

int meta_item_is_assigned(const void *ptr)
{
   return ((struct meta_item *) ptr)->def_path != NULL;
}

void meta_item_reset(void *ptr)
{
   struct meta_item *this = ptr;
   this->def_path = NULL;
}

void meta_item_store_undefined_value(void *ptr, void *arg)
{
   struct meta_item *this = ptr;
   struct header_parser *parser = arg;
   struct poliqarp_binary_metadata meta = {
      .type = POLIQARP_METADATA_UNDEFINED,
      .key = 0,
      .value_as.text = 0
   };

   if (this->def_path == NULL) {
      meta.key = this->key_node->id;
      store_meta(parser, &meta);
   }
}

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

struct meta_alias *meta_alias_create(struct binary_pool_node *key_node,
   struct list_item *list)
{
   struct meta_alias *this;
   this = malloc(sizeof *this);
   this->key_node = key_node;
   this->meta_list = list;
   return this;
}

void meta_alias_destroy(void *ptr)
{
   struct meta_alias *this = ptr;
   list_destroy(this->meta_list, NULL);
   free(this);
}

#if 0

void meta_alias_reslove_and_store(void *ptr, void *arg)
{
   this->type = POLIQARP_METADATA_SINGLE;
   this->key = key;
   this->value_as.text = value;

   struct header_parser *parser = arg;
   struct meta_alias *this = ptr;
   struct list_item *list_item;

   list_item = list_find(this->meta_list, meta_item_is_assigned);
   if (list_item) {
      struct meta_item *item;
      struct binary_metadata meta;
      meta.type = item->type;
   }
}

#endif

