/*   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 <stdint.h>
#include <unistd.h>
#include <time.h>

#include <glib.h>
#include <glib/gthread.h>

#include <libxml/xmlmemory.h>

#include <wand/magick-wand.h>

#include <config.h>

#include "setup.h"
#include "job-manager.h"
#include "stats.h"
#include "atom-writer.h"
#include "gallery-utils.h"



/*  Commandline arguments  */
static gchar *source_dir = NULL;
static gchar *dst_dir = NULL;
static gboolean verbose = FALSE;
static gboolean update = FALSE;
static gboolean fullsize = FALSE;
static int jobs = 1;



/*
 *   parse_cmd: parse commandline and fill global variable parameters
 */
gboolean
parse_cmd (int argc, char *argv[])
{
  static GOptionEntry entries[] =
	{
          { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL },
          { "source", 's', 0, G_OPTION_ARG_STRING, &source_dir, "Specifies a path to source structure", NULL },
          { "output", 'o', 0, G_OPTION_ARG_STRING, &dst_dir, "Generate files to the specified directory instead of current", NULL },
          { "jobs", 'j', 0, G_OPTION_ARG_INT, &jobs, "Allow N jobs at once (default=1)", NULL },
          { "update", 'u', 0, G_OPTION_ARG_NONE, &update, "Update the output structure", NULL },
          { "fullsize", 'f', 0, G_OPTION_ARG_NONE, &fullsize, "Override the nofullsize switch and generate full gallery", NULL },
          { NULL }
	};

  GError *error = NULL;
  GOptionContext *context;
  gchar *s1;

  g_set_prgname ("cgg");

  context = g_option_context_new ("- web gallery generator");
  s1 = g_strdup_printf ("cgg v%s [%s]  %s", VERSION, APP_BUILD_DATE, APP_COPYRIGHT_STRING);
  g_option_context_set_summary (context, s1);
  g_free (s1);
  g_option_context_add_main_entries (context, entries, NULL);

  if (argc == 1) {
    s1 = g_option_context_get_help (context, TRUE, NULL);
    g_print ("%s", s1);
    g_free (s1);
    g_option_context_free (context);
    return FALSE;
  }

  if (! g_option_context_parse (context, &argc, &argv, &error)) {
    g_print ("option parsing failed: %s\n", error->message);
    s1 = g_option_context_get_help (context, TRUE, NULL);
    g_print ("%s", s1);
    g_free (s1);
    g_option_context_free (context);
    return FALSE;
  }
  g_option_context_free (context);

  return TRUE;
}



int
main (int argc, char* argv[])
{
  TGallerySetup *setup;
  time_t time_start = time (NULL);
  time_t time_stop;
  gchar *s;
  TPathInfo *path_info;

  /*
   * this initialize the library and check potential ABI mismatches
   * between the version it was compiled for and the actual shared
   * library used.
   */
  LIBXML_TEST_VERSION;

  g_thread_init (NULL);

  /*  Initialize ImageMagick at this point, for multithreading safety  */
  MagickWandGenesis();

  /*  Parse commandline  */
  if (! parse_cmd (argc, argv))
    return -1;

  if (! source_dir || access (source_dir, R_OK)) {
    fprintf (stderr, "error: source directory must be specified and pointing to valid structure\n");
    return -4;
  }
  if (! dst_dir) {
    fprintf (stderr, "error: target directory must be specified\n");
    return -5;
  }

  /*  Read gallery settings  */
  setup = find_setup_xml ();
  if (! setup) {
    fprintf (stderr, "error: could not parse gallery settings file\n");
    return -2;
  }

  setup->real_templates_dir = find_templates_directory (setup);
  if (setup->real_templates_dir == NULL) {
    fprintf (stderr, "error: could not determine templates directory\n");
    return -3;
  }


  stats_errors = 0;
  stats_dirs = 0;
  stats_images = 0;

  /*  Print banner  */
  if (verbose) {
    printf ("cgg v%s [%s]\n\n", VERSION, APP_BUILD_DATE);
    printf ("Using setup file \"%s\"\n", setup->setup_xml_path);
  }

  /*  Setup feeds  */
  news_feed = NULL;
  if (setup->feed_enabled) {
    news_feed = atom_writer_new ();
    atom_writer_set_title (news_feed, setup->feed_title ? setup->feed_title : setup->site_title);
  }

  /*  Start building the gallery tree  */
  setup->verbose = verbose;
  setup->update_mode = update;
  setup->override_nofullsize = fullsize;

  path_info = g_malloc0 (sizeof (TPathInfo));
  path_info->source_root = g_strdup (source_dir);
  path_info->src_dir = g_strdup (source_dir);
  path_info->dest_root = g_strdup (dst_dir);
  path_info->dest_dir = g_strdup (dst_dir);
  path_info->album_path = g_strdup ("/");
  build_tree (setup, path_info, NULL, -1, jobs);
  free_path_info (path_info);

  /*  Write feeds  */
  if (news_feed) {
    if (verbose)
      printf ("Writing Atom feed:  %s\n", setup->feed_filename);
    if (setup->feed_base_url == NULL || strlen (setup->feed_base_url) == 0)
      log_error ("Error: feed base URL not defined!\n");
    else
    if (setup->feed_filename == NULL || strlen (setup->feed_filename) == 0)
      log_error ("Error: feed file name not defined!\n");
    else {
      atom_writer_set_base_url (news_feed, setup->feed_base_url);
      s = g_build_filename (setup->feed_base_url, setup->feed_filename, NULL);
      atom_writer_set_feed_url (news_feed, s);
      g_free (s);

      s = g_strdup_printf ("%s/%s", dst_dir, setup->feed_filename);
      atom_writer_write_to_file (news_feed, s, setup);
      g_free (s);
    }
    atom_writer_free (news_feed);
  }

  /*  Write stats  */
  if (verbose) {
    time_stop = time (NULL);
    printf ("\nProcessed %d images in %d albums, elapsed time = %dm %ds\n", stats_images, stats_dirs, (int) ((time_stop - time_start) / 60), (int) ((time_stop - time_start) % 60));
    if (stats_errors == 1)
      printf ("%d error occured.\n", stats_errors);
    if (stats_errors > 1)
      printf ("%d errors occured.\n", stats_errors);
  }


  MagickWandTerminus();

  /*  Cleanup function for the XML library. */
  xmlCleanupParser();

  g_free (source_dir);
  g_free (dst_dir);
  free_setup_data (setup);

  return 0;
}
