/*
 * Copyright (c) 2002, 2003, 2004 Jean-Yves Lefort
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include <string.h>
#include <errno.h>
#include <glib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "sg-util.h"
#include "st-cache.h"
#include "st-config-load.h"
#include "st-config-save.h"
#include "st-dialog-api.h"
#include "st-settings.h"
#include "st-preselections.h"
#include "st-handlers.h"
#include "st-handler.h"
#include "st-category-store.h"
#include "st-oldcache-load.h"
#include "st-util-api.h"

/*** function declarations ***************************************************/

static gboolean st_session_mkdir (const char *dirname);

/*** implementation **********************************************************/

void
st_session_load (void)
{
  GError *err = NULL;
  GSList *l;
  
  if (g_file_test(st_settings.accels_file, G_FILE_TEST_IS_REGULAR))
    gtk_accel_map_load(st_settings.accels_file);

  if (g_file_test(st_settings.config_file, G_FILE_TEST_IS_REGULAR))
    {
      if (! st_config_load(st_settings.config_file, &err))
	{
	  char *normalized;

	  normalized = st_dialog_normalize(err->message);

	  st_error_dialog(_("Unable to load configuration"), "%s", normalized);

	  g_free(normalized);
	  g_clear_error(&err);
	}
    }

  if (g_file_test(st_settings.cache_dir, G_FILE_TEST_IS_REGULAR))
    {				/* old cache */
      if (! st_oldcache_load(st_settings.cache_dir, &err))
	{
	  char *normalized;

	  normalized = st_dialog_normalize(err->message);

	  st_error_dialog(_("Unable to load old cache"), "%s", normalized);

	  g_free(normalized);
	  g_clear_error(&err);
	}
    }
  else
    SG_LIST_FOREACH(l, st_handlers_list)
      {
	STHandler *handler = l->data;
	const char *name;

	if (ST_HANDLER_HAS_CATEGORIES(handler) && st_cache_has_categories(handler))
	  {
	    GNode *categories;
	    
	    categories = st_cache_load_categories(handler, &err);
	    if (categories)
	      {
		STCategoryStore *category_store;
		
		category_store = st_handler_get_categories(handler);
		st_category_store_append_node(category_store, categories);
		
		g_object_unref(category_store);
	      }
	    else
	      {
		char *primary;
		char *normalized;
		
		primary = g_strdup_printf(_("Unable to load categories of handler \"%s\" from cache"), st_handler_get_label(handler));
		normalized = st_dialog_normalize(err->message);
		
		st_error_dialog(primary, "%s", normalized);
		
		g_free(primary);
		g_free(normalized);
		
		g_clear_error(&err);
	      }
	  }
	
	name = st_handler_get_name(handler);
	if (! strcmp(name, "bookmarks") || ! strcmp(name, "preselections"))
	  {
	    if (st_cache_has_streams(handler, ST_CATEGORY_BAG_MAIN))
	      {
		STStreamStore *streams;
		
		streams = st_cache_load_streams(handler, ST_CATEGORY_BAG_MAIN, NULL, NULL, &err);
		if (streams)
		  {
		    st_handler_set_streams(handler, ST_CATEGORY_BAG_MAIN, streams);
		    g_object_unref(streams);
		  }
		else
		  {
		    const char *primary;
		    char *normalized;
		    
		    if (! strcmp(name, "bookmarks"))
		      primary = _("Unable to load bookmarks from cache");
		    else if (! strcmp(name, "preselections"))
		      primary = _("Unable to load preselections from cache");
		    else
		      g_return_if_reached();
		    
		    normalized = st_dialog_normalize(err->message);
		    
		    st_error_dialog(primary, "%s", normalized);
		    
		    g_free(normalized);
		    g_clear_error(&err);
		  }
	      }
	  }
      }
  
  st_preselections_add_stock();
}

void
st_session_save (void)
{
  GError *err = NULL;

  /* remove old cache if present */

  if (g_file_test(st_settings.cache_dir, G_FILE_TEST_IS_REGULAR))
    unlink(st_settings.cache_dir);

  if (g_file_test(st_settings.images_dir, G_FILE_TEST_IS_DIR))
    {
      GDir *dir;

      dir = g_dir_open(st_settings.images_dir, 0, NULL);
      if (dir)
	{
	  const char *filename;

	  while ((filename = g_dir_read_name(dir)))
	    {
	      char *extension;

	      extension = strrchr(filename, '.');
	      if (extension && ! strcmp(extension, ".png"))
		{
		  char *base;

		  base = g_strndup(filename, extension - filename);
		  if (st_str_like(base, ST_NUMERIC))
		    {
		      char *pathname;

		      pathname = g_build_filename(st_settings.images_dir, filename, NULL);
		      unlink(pathname);
		      g_free(pathname);
		    }
		  g_free(base);
		}
	    }

	  g_dir_close(dir);
	}

      rmdir(st_settings.images_dir);
    }
  
  /* create directories */

  if (! st_session_mkdir(st_settings.private_dir))
    return;
  if (! st_session_mkdir(st_settings.cache_dir))
    return;

  /* save accel map */

  gtk_accel_map_save(st_settings.accels_file);

  /* save config */

  if (! st_config_save(st_settings.config_file, &err))
    {
      char *normalized;
      
      normalized = st_dialog_normalize(err->message);
      
      st_error_dialog(_("Unable to save configuration"), "%s", normalized);
      
      g_free(normalized);
      g_clear_error(&err);
    }
  
  /* save cache */

  if (! st_cache_save(&err))
    {
      char *normalized;
      
      normalized = st_dialog_normalize(err->message);
      
      st_error_dialog(_("Unable to save cache"), "%s", normalized);
      
      g_free(normalized);
      g_clear_error(&err);
    }

  /* save status of splash */

  if (! st_settings_save_splash_enabled(&err))
    {
      char *normalized;
      
      normalized = st_dialog_normalize(err->message);
      
      st_error_dialog(_("Unable to save splash screen setting"), "%s", normalized);
      
      g_free(normalized);
      g_clear_error(&err);
    }

  /* save list of disabled plugins */

  if (! st_settings_save_disabled_plugins_list(&err))
    {
      char *normalized;
      
      normalized = st_dialog_normalize(err->message);
      
      st_error_dialog(_("Unable to save list of disabled plugins"), "%s", normalized);
      
      g_free(normalized);
      g_clear_error(&err);
    }
}

static gboolean
st_session_mkdir (const char *dirname)
{
  gboolean status = TRUE;

  if (! g_file_test(dirname, G_FILE_TEST_IS_DIR))
    {
      if (mkdir(dirname, 0755) < 0)
	{
	  char *secondary;
	  char *normalized;

	  secondary = g_strdup_printf("Unable to create directory %s: %s.",
				      dirname, g_strerror(errno));
	  normalized = st_dialog_normalize(secondary);
	  g_free(secondary);

	  st_error_dialog(_("Unable to save session"), "%s", normalized);
	  g_free(normalized);

	  status = FALSE;
	}
    }

  return status;
}
