/*   Cataract - Static web photo gallery generator
 *   Copyright (C) 2008 Tomas Bzatek <tbzatek@users.sourceforge.net>
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   as published by the Free Software Foundation; either version 2
 *   of the License, or any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>

#include "items.h"
#include "xml-parser.h"
#include "gallery-utils.h"
#include "atom-writer.h"



static void
free_album_item (TIndexItem *item)
{
  g_free (item->path);
  g_free (item->title);
  g_free (item->title_description);
  g_free (item->thumbnail);
  g_free (item->preview);
  g_free (item->border_style);
  g_free (item);
}


/*
 *   parse_album_xml: XML parser for gallery index.xml files
 */
TAlbum *
parse_album_xml (const gchar *filename, TPathInfo *path_info)
{
  TXMLFile *xml;
  gchar *gallery_type;
  int count;
  int i;
  gchar *s, *s2;
  gchar *node_name;
  gchar *base_dir;
  TIndexItem *item;
  TAtomFeedItem *feed_item;
  TAlbum *index;

  xml = xml_parser_load (filename);
  if (xml == NULL)
    return NULL;

  index = g_malloc0 (sizeof (TAlbum));

  /*  Retrieve gallery type  */
  gallery_type = xml_file_get_node_attribute (xml, "/gallery", "type");
  if (strcmp (gallery_type, "index") == 0)
    index->type = GALLERY_TYPE_INDEX;
  else
  if (strcmp (gallery_type, "album") == 0)
    index->type = GALLERY_TYPE_ALBUM;
  else {
    log_error ("Invalid gallery type (%s)\n", gallery_type);
    g_free (gallery_type);
    free_album_data (index);
    return NULL;
  }
  g_free (gallery_type);

  base_dir = g_path_get_dirname (filename);

  /*  Section General  */
  index->ID = xml_file_get_node_value (xml, "/gallery/general/ID/text()");
  index->title = xml_file_get_node_value (xml, "/gallery/general/title/text()");
  index->desc = xml_file_get_node_value (xml, "/gallery/general/description/text()");
  index->footnote = xml_file_get_node_value (xml, "/gallery/general/footnote/text()");
  s = xml_file_get_node_value (xml, "/gallery/general/extra_files/text()");
  if (s) {
    index->extra_files = g_strsplit (s, "\n", -1);
    g_free (s);
  }

  index->quality = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "quality", -1);
  index->landscape_width = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "landscape_w", 0);
  index->landscape_height = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "landscape_h", 0);
  index->portrait_width = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "portrait_w", 0);
  index->portrait_height = xml_file_get_node_attribute_long (xml, "/gallery/general/images", "portrait_h", 0);

  index->border_style = xml_file_get_node_attribute (xml, "/gallery/general/border", "style");
  index->meta_author = xml_file_get_node_value (xml, "/gallery/general/meta/author/text()");
  index->meta_description = xml_file_get_node_value (xml, "/gallery/general/meta/description/text()");
  index->meta_keywords = xml_file_get_node_value (xml, "/gallery/general/meta/keywords/text()");

  index->nofullsize = xml_file_get_node_present (xml, "/gallery/general/nofullsize");
  index->fullsize = xml_file_get_node_present (xml, "/gallery/general/fullsize");

  /*  News records  */
  if (news_feed) {
    count = xml_file_node_get_children_count (xml, "/gallery/general/news");
    for (i = 0; i < count; i++) {
      feed_item = atom_writer_add_item (news_feed);
      s = g_strdup_printf ("/gallery/general/news[%d]", i + 1);

      s2 = xml_file_get_node_attribute (xml, s, "title");
      atom_feed_item_set_title (feed_item, s2);
      g_free (s2);

      s2 = xml_file_get_node_attribute (xml, s, "timestamp");
      atom_feed_item_set_date (feed_item, s2);
      g_free (s2);

      s2 = xml_file_get_node_attribute (xml, s, "type");
      atom_feed_item_set_summary_type (feed_item, s2);
      g_free (s2);
      g_free (s);

      s = g_strdup_printf ("/gallery/general/news[%d]/text()", i + 1);
      s2 = xml_file_get_node_value (xml, s);
      g_free (s);
      atom_feed_item_set_summary (feed_item, s2);
      g_free (s2);

      atom_feed_item_set_path (feed_item, path_info->album_path);
    }
  }

  /*  Section Items  */
  count = xml_file_node_get_children_count (xml, "/gallery/items/*");
  index->items = g_ptr_array_new ();

  for (i = 0; i < count; i++) {
    s = g_strdup_printf ("/gallery/items/*[%d]", i + 1);
    node_name = xml_file_get_node_name (xml, s);
    g_free (s);
    if (! node_name)
      continue;

    item = g_malloc0 (sizeof (TIndexItem));

    if (strcmp (node_name, "item") == 0) {
      item->type = INDEX_ITEM_TYPE_PICTURE;

      s = g_strdup_printf ("/gallery/items/*[%d]", i + 1);
      if (index->type == GALLERY_TYPE_INDEX)
        item->path = xml_file_get_node_attribute (xml, s, "path");
      else
        item->path = xml_file_get_node_attribute (xml, s, "src");
      item->preview = xml_file_get_node_attribute (xml, s, "preview");
      item->quality = xml_file_get_node_attribute_long (xml, s, "quality", -1);
      item->width = xml_file_get_node_attribute_long (xml, s, "width", 0);
      item->height = xml_file_get_node_attribute_long (xml, s, "height", 0);
      item->border_style = xml_file_get_node_attribute (xml, s, "border");
      if (index->type == GALLERY_TYPE_ALBUM)
        item->thumbnail = xml_file_get_node_attribute (xml, s, "thumbnail");
      g_free (s);

      s = g_strdup_printf ("/gallery/items/*[%d]/title/text()", i + 1);
      item->title = xml_file_get_node_value (xml, s);
      g_free (s);

      s = g_strdup_printf ("/gallery/items/*[%d]/title_description/text()", i + 1);
      item->title_description = xml_file_get_node_value (xml, s);
      g_free (s);

      if (index->type == GALLERY_TYPE_INDEX) {
        s = g_strdup_printf ("/gallery/items/*[%d]/thumbnail", i + 1);
        item->thumbnail = xml_file_get_node_attribute (xml, s, "src");
        g_free (s);
      }

      s = g_strdup_printf ("/gallery/items/*[%d]/nofullsize", i + 1);
      item->force_nofullsize = (xml_file_get_node_present (xml, s) || item->path == NULL);
      g_free (s);

      s = g_strdup_printf ("/gallery/items/*[%d]/fullsize", i + 1);
      item->force_fullsize = xml_file_get_node_present (xml, s);
      g_free (s);

      s = g_strdup_printf ("/gallery/items/*[%d]/hidden", i + 1);
      item->hidden = (xml_file_get_node_present (xml, s));
      g_free (s);

      /*  Retrieve title and description from linked album if not defined here  */
      if (index->type == GALLERY_TYPE_INDEX &&
          item->title == NULL && item->title_description == NULL) {
        s = g_build_filename (base_dir, item->path, "index.xml", NULL);
        get_album_titles (s, &item->title, &item->title_description, NULL);
        g_free (s);
      }

      /*  Retrieve thumbnail from linked album if not defined here  */
      if (index->type == GALLERY_TYPE_INDEX && item->thumbnail == NULL) {
        s = g_build_filename (base_dir, item->path, "index.xml", NULL);
        s2 = NULL;
        get_album_titles (s, NULL, NULL, &s2);
        if (s2) {
          item->thumbnail = g_build_filename (item->path, s2, NULL);
          g_free (s2);
        }
        g_free (s);
      }

      if (item->path || item->preview) {
        g_ptr_array_add (index->items, item);
      } else {
        log_error ("%s: No image src specified, skipping!\n", filename);
        free_album_item (item);
      }
    }
    else
    if (strcmp (node_name, "separator") == 0) {
      item->type = INDEX_ITEM_TYPE_SEPARATOR;

      s = g_strdup_printf ("/gallery/items/*[%d]/text()", i + 1);
      item->title = xml_file_get_node_value (xml, s);
      g_free (s);

      g_ptr_array_add (index->items, item);
    }
    else
    if (strcmp (node_name, "interspace") == 0) {
      item->type = INDEX_ITEM_TYPE_INTERSPACE;

      s = g_strdup_printf ("/gallery/items/*[%d]/text()", i + 1);
      item->title = xml_file_get_node_value (xml, s);
      g_free (s);

      g_ptr_array_add (index->items, item);
    }
    else {
      /*  Free the item if nobody cares  */
      g_free (item);
    }
    g_free (node_name);
  }

  xml_parser_free (xml);
  g_free (base_dir);

  return index;
}


/*
 *   free_album_data: free allocated album data
 */
void
free_album_data (TAlbum *album)
{
  if (album) {
    g_free (album->ID);
    g_free (album->title);
    g_free (album->desc);
    g_free (album->footnote);
    g_free (album->border_style);
    g_free (album->meta_author);
    g_free (album->meta_description);
    g_free (album->meta_keywords);
    g_strfreev (album->extra_files);

    if (album->items) {
      g_ptr_array_foreach (album->items, (GFunc) free_album_item, NULL);
      g_ptr_array_free (album->items, TRUE);
    }
    g_free (album);
  }
}


/*
 *   get_gallery_objects_count: retrieve number of items in specified album
 */
int
get_album_objects_count (const gchar *filename)
{
  TXMLFile *xml;
  int count, hidden;

  xml = xml_parser_load (filename);
  if (xml == NULL)
    return 0;

  count = xml_file_node_get_children_count (xml, "/gallery/items/item");
  hidden = xml_file_node_get_children_count (xml, "/gallery/items/item/hidden");

  xml_parser_free (xml);
  return (count - hidden);
}

/*
 *   get_album_titles: retrieve title, description and first thumbnail from specified album
 */
void
get_album_titles (const gchar *filename, gchar **title, gchar **description, gchar **thumbnail)
{
  TXMLFile *xml;

  xml = xml_parser_load (filename);
  if (xml == NULL)
    return;

  if (title)
    *title = xml_file_get_node_value (xml, "/gallery/general/title/text()");
  if (description)
    *description = xml_file_get_node_value (xml, "/gallery/general/description/text()");
  if (thumbnail) {
    *thumbnail = xml_file_get_node_attribute (xml, "/gallery/items/item[1]/thumbnail", "src");
    if (! *thumbnail)
      *thumbnail = xml_file_get_node_attribute (xml, "/gallery/items/item[1]", "src");
    if (! *thumbnail)
      *thumbnail = xml_file_get_node_attribute (xml, "/gallery/items/item[1]", "preview");
  }

  xml_parser_free (xml);
}

/*
 *   free_path_info: free allocated pathinfo data
 */
void
free_path_info (TPathInfo *path_info)
{
  if (path_info) {
    g_free (path_info->source_root);
    g_free (path_info->dest_root);
    g_free (path_info->src_dir);
    g_free (path_info->dest_dir);
    g_free (path_info);
  }
}
