/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 2004 The GNOME Foundation
 *
 * 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 (at your option) 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Authors:
 *   Paolo Borelli
 */

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <libxml/tree.h>
#include <libxml/xmlwriter.h>

#include "glade.h"
#include "glade-project-window.h"
#include "glade-session.h"

/* do we care about persisting the window dimension? */
static int
write_window_geometry (FILE *file,
		       GtkWindow *window,
		       const char *id)
{
	int x = 0, y = 0;
	int width = 0, height = 0;
	int ret;

	/* get window geometry */
	gtk_window_get_size (window, &width, &height);
	gtk_window_get_position (window, &x, &y);

	ret = fprintf(file, 
		      "\t<window id=\"%s\" x=\"%d\" y=\"%d\" "
		      "width=\"%d\" height=\"%d\"/>\n", 
		      id, x, y, width, height);

	return ret;
}

static int
glade_session_write_geometry (FILE *file)
{
	GladeProjectWindow *gpw;
	int ret;

	gpw = glade_project_window_get ();

	/* project window */
	ret = write_window_geometry (file, GTK_WINDOW (gpw->window), 
				     "project-window");
	if (ret < 0)
		return ret;

	/* palette */
	ret = write_window_geometry (file, gpw->palette_window, 
				     "palette");
	if (ret < 0)
		return ret;

	/* editor */
	ret = write_window_geometry (file, gpw->editor_window, 
				     "editor");
	if (ret < 0)
		return ret;
#if 0
	/* widget tree */
	ret = write_window_geometry (file, GTK_WINDOW (gpw->widget_tree), 
				     "widget-tree");
	if (ret < 0)
		return ret;

	/* clipboard */
	ret = write_window_geometry (file, GTK_WINDOW (gpw->clipboard->view), 
				     "clipboard");
	if (ret < 0)
		return ret;
#endif
	return ret;
}

gboolean
switch_temp_file (const char *filename,
		  const char *filename_temp)
{
	char *old_file;
	gboolean old_exist;
	gboolean retval = TRUE;

	old_file = g_strconcat (filename, ".old", NULL);

	old_exist = g_file_test (filename, G_FILE_TEST_EXISTS);

	if (old_exist)
	{
		if (rename (filename, old_file) < 0)
		{
			g_warning ("Failed to rename %s to %s", filename, old_file);
			retval = FALSE;
			goto failed;
		}
	}

	if (rename (filename_temp, filename) < 0)
	{
		g_warning ("Failed to rename %s to %s", filename_temp, filename);

		if (rename (old_file, filename) < 0)
		{
			g_warning ("Failed to restore %s from %s",
				   filename, filename_temp);
		}
		retval = FALSE;
		goto failed;
	}

	if (old_exist)
	{
		if (unlink (old_file) < 0)
		{
			g_warning ("Failed to delete old file %s", old_file);
		}
	}

failed:
	g_free (old_file);

	return retval;
}

/* FIXME: hardcoded for now... */
#define GLADE_RCDIR "/.glade"
#define SESSION_FILE "/session"

void
glade_session_save (void)
{
	FILE *file = NULL;
	char *tmp_file = NULL;
	char *glade_rcdir = NULL;
	char *session_file = NULL;
	int ret;

	glade_rcdir = g_strconcat (g_get_home_dir (), GLADE_RCDIR, NULL);
	session_file = g_strconcat (glade_rcdir, SESSION_FILE, NULL);
	tmp_file = g_strconcat (session_file, ".tmp", NULL);

	if (!g_file_test (glade_rcdir, G_FILE_TEST_EXISTS)) 
	{
		if (mkdir (glade_rcdir, 0777) == -1)
			goto out;
	}

	file = fopen (tmp_file, "w");
	if (!file) 
        {
		g_warning ("Failed to create temporary file: %s",
			   tmp_file);
		goto out;
	}

	fprintf (file, 
		 "<?xml version=\"1.0\"?>\n"
		 "<session>\n");

	/* save positions and size of gui elements */
	ret = glade_session_write_geometry (file);
	if (ret < 0) 
        {
		g_warning ("Failed to write session information.");
		goto out;
	}

	fprintf (file, "</session>\n");

	if (ret >= 0)
		switch_temp_file (session_file, tmp_file);

out:
	if (file)
		fclose (file);
	unlink (tmp_file);
	g_free (tmp_file);
	g_free (session_file);

	return;
}

void
restore_window_geometry (xmlNodePtr child, GtkWidget *window)
{
	xmlChar *tmp;
	int x, y;

	g_return_if_fail (GTK_IS_WINDOW (window));

	tmp = xmlGetProp (child, "x");
	sscanf (tmp, "%d", &x);
	g_free (tmp);

	tmp = xmlGetProp (child, "y");
	sscanf (tmp, "%d", &y);
	g_free (tmp);

	gtk_window_move (GTK_WINDOW (window), x, y);
}

void
glade_session_restore (void)
{
	GladeProjectWindow *gpw;
	xmlDocPtr doc;
        xmlNodePtr child;
	char *session_file;

	gpw = glade_project_window_get ();

	session_file = g_strconcat (g_get_home_dir (), GLADE_RCDIR, 
				    SESSION_FILE, NULL);
	doc = xmlParseFile (session_file);
	g_free (session_file);

	if (!doc)
		return;

	child = xmlDocGetRootElement (doc);

	for (child = child->children; child; child = child->next)
	{
		xmlChar *id;

		if (!xmlStrEqual (child->name, "window"))
			continue;

		id = xmlGetProp (child, "id");

		if (id && xmlStrEqual ("project-window", id))
			restore_window_geometry (child, gpw->window);
		else if (id && xmlStrEqual ("palette", id))
			restore_window_geometry (child, GTK_WIDGET(gpw->palette_window));
		else if (id && xmlStrEqual ("editor", id))
			restore_window_geometry (child, GTK_WIDGET(gpw->editor_window));
//		else if (id && xmlStrEqual ("widget-tree", id))
//			restore_window_geometry (child, gpw->widget_tree);
//		else if (id && xmlStrEqual ("clipboard", id))
//			restore_window_geometry (child, gpw->clipboard->view);
	}

	xmlFreeDoc (doc);
}

