/* Bluefish HTML Editor
 * project.c - this file contains the project and project edit code
 *
 * Copyright (C) 2000 Olivier Sessink
 *
 * 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
 */
#include "default_include.h"

#include <string.h>  /* memset() */

#include "bluefish.h"
#include "bf_lib.h"
#include "stringlist.h"			/*add to stringlist */
#include "menu.h"				/* menu translate */
#include "gtk_easy.h"			/* window_with_title */
#include "init.h"				/* make_config_list_item */
#include "document.h"			/* file_close_cb */
#include "project.h"			/* myself ;-) */
#include "interface.h"  /* notebook_changed() */

/* this struct is used for the project editor */
typedef struct {
	GtkWidget *window;
	GtkWidget *base_entry;
	GtkWidget *web_entry;
	GtkWidget *templ_entry;
} Teditproject;

/* a global variable for reading and writing projects */
static GList *project_list = NULL;

/********************************************************************/

static void project_edit_list_lcb(GtkWidget * widget, gpointer data)
{
	switch (GPOINTER_TO_INT(data)) {
	case 1:
		DEBUG_MSG("project_edit_list, before, main_v->current_project.filenames(%p)\n", main_v->current_project.filenames);
		estrl_dialog(&main_v->current_project.filenames, _("Bluefish project - files"), GPOINTER_TO_INT(data), 0, NULL, NULL);
		DEBUG_MSG("project_edit_list, after, main_v->current_project.filenames(%p)\n", main_v->current_project.filenames);
		break;
	case 2:
		estrl_dialog(&main_v->current_project.colorlist, _("Bluefish project - colorlist"), GPOINTER_TO_INT(data), 0, NULL, NULL);
		break;
	case 3:
		estrl_dialog(&main_v->current_project.fontlist, _("Bluefish project - fontlist"), GPOINTER_TO_INT(data), 0, NULL, NULL);
		break;
	case 4:
		estrl_dialog(&main_v->current_project.urllist, _("Bluefish project - urllist"), GPOINTER_TO_INT(data), 0, NULL, NULL);
		break;
	case 5:
		main_v->current_project.targetlist = add_to_stringlist(main_v->current_project.targetlist, "_top");
		main_v->current_project.targetlist = add_to_stringlist(main_v->current_project.targetlist, "_blank");
		main_v->current_project.targetlist = add_to_stringlist(main_v->current_project.targetlist, "_self");
		main_v->current_project.targetlist = add_to_stringlist(main_v->current_project.targetlist, "_parent");
		estrl_dialog(&main_v->current_project.targetlist, _("Bluefish project - targetlist"), GPOINTER_TO_INT(data), 0, NULL, NULL);
		break;
	case 6:
		estrl_dialog(&main_v->current_project.dtd_cblist, _("Bluefish project - dtd_cblist"), GPOINTER_TO_INT(data), 0, NULL, NULL);
		break;
	case 7:
		estrl_dialog(&main_v->current_project.classlist, _("Bluefish project - classlist"), GPOINTER_TO_INT(data), 0, NULL, NULL);
		break;
	case 8:
		estrl_dialog(&main_v->current_project.headerlist, _("Bluefish project - headers"), GPOINTER_TO_INT(data), 0, NULL, NULL);
		break;
	default:

		break;
	}
}

static void project_edit_destroy_lcb(GtkWidget * widget, GdkEvent *event, Teditproject * data) {
	window_destroy(data->window);
	g_free(data);
}

static void project_edit_cancel_lcb(GtkWidget * widget, gpointer data) {
	project_edit_destroy_lcb(NULL, NULL, data);
}


static void project_edit_ok_lcb(GtkWidget * widget, Teditproject * data)
{
	string_apply(&main_v->current_project.basedir, data->base_entry);
	string_apply(&main_v->current_project.webdir, data->web_entry);
	string_apply(&main_v->current_project.template, data->templ_entry);
	DEBUG_MSG("project_edit_ok, main_v->current_project.webdir(%p)=%s\n", main_v->current_project.webdir, main_v->current_project.webdir);
	main_v->current_project.modified = 1;
	project_edit_destroy_lcb(NULL, NULL, data);
}



void project_add_document_cb(GtkWidget * widget, gpointer data)
{

	GList *tmplist;
	Tdocument *doc;

	if (GPOINTER_TO_INT(data) == 0) {
		DEBUG_MSG("project_add_document, adding current file\n");
		if (main_v->current_document->filename != NULL) {
			main_v->current_project.filenames = add_to_stringlist(main_v->current_project.filenames, main_v->current_document->filename);
		} else {
			/*statusbar message needed !!!!!!!!!!!!!!!!!!!!! */
		}
	} else {
		DEBUG_MSG("project_add_document, adding ALL files\n");
		tmplist = g_list_first(main_v->documentlist);
		while (tmplist != NULL) {
			doc = (Tdocument *) tmplist->data;
			if ((doc != NULL) && (doc->filename != NULL)) {
				main_v->current_project.filenames = add_to_stringlist(main_v->current_project.filenames, doc->filename);
			}
			tmplist = g_list_next(tmplist);
		}
	}
	main_v->current_project.modified = 1;
}





/***************************************************** 
 *
 *           project edit functions
 *
 *****************************************************/


static GtkWidget *string_entry(gchar * labeltext, GtkWidget * table, gchar * which_config_string, gint left, gint right, gint top, gint bottom)
{

	GtkWidget *label, *tmpentry;

	label = gtk_label_new(labeltext);
	gtk_table_attach_defaults(GTK_TABLE(table), label, left, right, top, bottom - 1);
	tmpentry = entry_with_text(which_config_string, 1023);
	gtk_table_attach_defaults(GTK_TABLE(table), tmpentry, left, right, top + 1, bottom);
	return tmpentry;
}


static GtkItemFactoryEntry menu_items[] = {
	{N_("/_Files"), NULL, NULL, 0, "<Branch>"},
	{N_("/Files/Files"), NULL, project_edit_list_lcb, 1, NULL},
	{N_("/_Lists"), NULL, NULL, 0, "<Branch>"},
	{N_("/Lists/Colors"), NULL, project_edit_list_lcb, 2, NULL},
	{N_("/Lists/Fonts"), NULL, project_edit_list_lcb, 3, NULL},
	{N_("/Lists/Url's"), NULL, project_edit_list_lcb, 4, NULL},
	{N_("/Lists/Targets"), NULL, project_edit_list_lcb, 5, NULL},
	{N_("/Lists/Document type definitions"), NULL, project_edit_list_lcb, 6, NULL},
	{N_("/Lists/CSS classes"), NULL, project_edit_list_lcb, 7, NULL},
	{N_("/Lists/headers"), NULL, project_edit_list_lcb, 8, NULL}
};

static void get_project_edit_menu(GtkWidget * window, GtkWidget ** menubar)
{
	GtkItemFactory *item_factory;
	GtkAccelGroup *accel_group;
	gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);

	accel_group = gtk_accel_group_new();
	item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
	gtk_item_factory_set_translate_func(item_factory, menu_translate, "<main>", NULL);
	gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
	gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
	if (menubar)
		*menubar = gtk_item_factory_get_widget(item_factory, "<main>");
}

void project_edit_cb(GtkWidget * widget, gpointer data)
{
	GtkWidget *table, *ok_b, *cancel_b, *but_templ, *menubar;
	Teditproject *editproject;

	editproject = g_malloc(sizeof(Teditproject));
	editproject->window = window_full(main_v->current_project.filename, GTK_WIN_POS_MOUSE
		, GTK_WINDOW_TOPLEVEL, 5, project_edit_destroy_lcb, editproject);

	table = gtk_table_new(8, 4, 1);
	gtk_container_add(GTK_CONTAINER(editproject->window), table);

	get_project_edit_menu(editproject->window, &menubar);
	gtk_table_attach_defaults(GTK_TABLE(table), menubar, 0, 4, 0, 1);

	editproject->base_entry = string_entry(_("Basedir"), table, main_v->current_project.basedir, 0, 3, 1, 3);
	editproject->web_entry = string_entry(_("Webdir"), table, main_v->current_project.webdir, 0, 3, 3, 5);
	editproject->templ_entry = string_entry(_("Template"), table, main_v->current_project.template, 0, 3, 5, 7);

	ok_b = bf_stock_ok_button(GTK_SIGNAL_FUNC(project_edit_ok_lcb), editproject);
	cancel_b = bf_stock_cancel_button(GTK_SIGNAL_FUNC(project_edit_cancel_lcb), editproject);
	gtk_table_attach_defaults(GTK_TABLE(table), ok_b, 0, 2, 7, 8);
	gtk_table_attach_defaults(GTK_TABLE(table), cancel_b, 2, 4, 7, 8);

	gtk_widget_realize(editproject->window);
	but_templ = file_but_new(editproject->templ_entry, editproject->window, 1);
	gtk_table_attach_defaults(GTK_TABLE(table), but_templ, 3, 4, 6, 7);
	gtk_widget_set_usize(editproject->window, 400, 0);
	gtk_widget_show_all(editproject->window);
}



/*******************************************
 *    
 *        other project functions
 *
 ********************************************/
static GList *create_project_list(GList * project_list)
{
	if (project_list == NULL) {
		/* this should be done only once !!!!!!!!!!! */
		project_list = make_config_list_item(project_list, &main_v->current_project.basedir, 's', "basedir:");
		project_list = make_config_list_item(project_list, &main_v->current_project.webdir, 's', "webdir:");
		project_list = make_config_list_item(project_list, &main_v->current_project.template, 's', "template:");
		project_list = make_config_list_item(project_list, &main_v->current_project.fontlist, 'l', "fontlist:");
		project_list = make_config_list_item(project_list, &main_v->current_project.urllist, 'l', "urllist:");
		project_list = make_config_list_item(project_list, &main_v->current_project.targetlist, 'l', "targetlist:");
		project_list = make_config_list_item(project_list, &main_v->current_project.colorlist, 'l', "colorlist:");
		project_list = make_config_list_item(project_list, &main_v->current_project.dtd_cblist, 'l', "dtd_cblist:");
		project_list = make_config_list_item(project_list, &main_v->current_project.classlist, 'l', "classlist:");
		project_list = make_config_list_item(project_list, &main_v->current_project.headerlist, 'l', "metalist:");
		project_list = make_config_list_item(project_list, &main_v->current_project.filenames, 'l', "filenames:");
	}
	return project_list;
}

static gint test_modified_docs_in_project() {

	GList *tmpdoclist, *tmpprolist;

	DEBUG_MSG("test_modified_docs_in_project, doclist len=%d, prolist len=%d\n"
			,g_list_length(main_v->documentlist)
			,g_list_length(main_v->current_project.filenames));
	tmpdoclist = g_list_first(main_v->documentlist);
	while (tmpdoclist) {
		tmpprolist = g_list_first(main_v->current_project.filenames);
		while (tmpprolist) {

                     if  (((Tdocument*)tmpdoclist->data)->filename) { 
                          if (strcmp(((Tdocument *)tmpdoclist->data)->filename, (gchar *) tmpprolist->data) == 0) {
                               
                               if (((Tdocument *)tmpdoclist->data)->modified) {
                                  return 1;
                             }
                          }
                     }
			tmpprolist = g_list_next(tmpprolist);
                
		}
		tmpdoclist = g_list_next(tmpdoclist);
	}
	return 0;
}


static void project_empty(void)
{

	GList *tmpdoclist, *tmpprolist;
	Tdocument *tmpdoc;
	gint retval;

	DEBUG_MSG("project_close, closing files that are in current project\n");
	DEBUG_MSG("project_close, project filenames(%p)\n", main_v->current_project.filenames);

	if (test_modified_docs_in_project()) {
		gchar *options[] = {N_("save all"), N_("close all"), N_("choose per file"), N_("cancel"), NULL};
		retval =	multi_button_dialog(_("Bluefish warning: some file(s) are modified!"), 3, _("Some file(s) in your project are modified\nplease choose your action"), options);
		if (retval == 3) {
			DEBUG_MSG("project_empty, cancel clicked, returning 0\n");
			return;
		}
	} else {
		retval = 1;
	}

	tmpdoclist = g_list_first(main_v->documentlist);
	while (tmpdoclist) {
		tmpdoc = (Tdocument *) tmpdoclist->data;
		if (test_only_empty_doc_left(tmpdoc)) {
			DEBUG_MSG("project_empty, only an empty doc left, break loop\n");
			break;
		}
	
		tmpprolist = g_list_first(main_v->current_project.filenames);
                if (tmpdoc->filename == NULL) {
                     tmpprolist = NULL;
                }
		while (tmpprolist && tmpdoclist) {
			if (strcmp(tmpdoc->filename, (gchar *) tmpprolist->data) == 0) {
				switch (retval) {
				case 0:
					doc_save(tmpdoc, 0, 0);
					doc_destroy(tmpdoc);
					tmpdoclist = NULL;
				break;
				case 1:
					doc_destroy(tmpdoc);
					tmpdoclist = NULL;
				break;
				case 2:
					if (doc_close(tmpdoc, 0)) {
						tmpdoclist = NULL;
					} else {
						notebook_changed();
						return;
					}
				break;
				default:
					notebook_changed();
					return;
				break;
				}
				tmpprolist = g_list_last(tmpprolist);
			} else {
				tmpprolist = g_list_next(tmpprolist);
			}
		}
		if (tmpdoclist == NULL) {
			tmpdoclist = g_list_first(main_v->documentlist);
		} else {
			tmpdoclist = g_list_next(tmpdoclist);
		}
	}

	g_free(main_v->current_project.basedir);
	g_free(main_v->current_project.webdir);
	g_free(main_v->current_project.template);
	g_free(main_v->current_project.filename);
	free_stringlist(main_v->current_project.fontlist);
	free_stringlist(main_v->current_project.urllist);
	free_stringlist(main_v->current_project.targetlist);
	free_stringlist(main_v->current_project.colorlist);
	free_stringlist(main_v->current_project.dtd_cblist);
	free_stringlist(main_v->current_project.classlist);
	free_stringlist(main_v->current_project.headerlist);
	DEBUG_MSG("empty_project, doclist len=%d, prolist len=%d\n"
			,g_list_length(main_v->documentlist)
			,g_list_length(main_v->current_project.filenames));
	free_stringlist(main_v->current_project.filenames);
	memset(&main_v->current_project, 0, sizeof(Tproject));
	DEBUG_MSG("empty_project, doclist len=%d, prolist len=%d\n"
			,g_list_length(main_v->documentlist)
			,g_list_length(main_v->current_project.filenames));	
	main_v->current_project.modified = 0;
}

void project_from_file(void)
{
	gchar *tmpstring;

	DEBUG_MSG("project_from_file, started, checking if project_list exists\n");
	project_list = create_project_list(project_list);

	DEBUG_MSG("project_from_file, project_list is (or even was) loaded\n");
	if (main_v->current_project.filename == NULL) {
		/* can't load it ??!! */
		DEBUG_MSG("project_from_file, current_project.filename == NULL!! error!!!\n");
		/* there should be a statusbar message here */
		return;
	}

	/* now we should close all open files or not? */
	DEBUG_MSG("project_from_file, parse config files about to start\n");
	parse_config_file(project_list, main_v->current_project.filename);
	DEBUG_MSG("project_from_file, parse config files ready\n");
	tmpstring = g_strconcat(CURRENT_VERSION_NAME, " ", main_v->current_project.filename, NULL);
	gtk_window_set_title(GTK_WINDOW(main_v->main_window), tmpstring);
	DEBUG_MSG("project_from_file, setting title to %s\n", tmpstring);
	g_free(tmpstring);

	/* then we should open the files from the project */
	docs_new_from_files(main_v->current_project.filenames);

	main_v->current_project.modified = 0;
	change_dir(main_v->current_project.basedir);
  populate_dir_file_list();
	populate_dir_history();
}

void project_to_file(void)
{
	gchar *tmpstring;

	project_list = create_project_list(project_list);
	DEBUG_MSG("project_to_file, main_v->current_project.filename(%p)=%s\n", main_v->current_project.filename,
			  main_v->current_project.filename);
	DEBUG_MSG("project_to_file, project_list(%p)\n", project_list);
	save_config_file(project_list, main_v->current_project.filename);
	tmpstring = g_strconcat(CURRENT_VERSION_NAME, " ", main_v->current_project.filename, NULL);
	gtk_window_set_title(GTK_WINDOW(main_v->main_window), tmpstring);
	g_free(tmpstring);
	main_v->current_project.modified = 0;
}

void project_open_cb(GtkWidget * widget, gpointer data)
{
	gchar *tmpfilename;

	/* change dir into project dir */
	tmpfilename = g_strconcat(g_get_home_dir(), "/.bluefish/projects/", NULL);
	DEBUG_MSG("project_open, change_dir(%s)\n", tmpfilename);
	change_dir(tmpfilename);
	g_free(tmpfilename);
	DEBUG_MSG("project_open, main_v->current_project.filename=%p\n", main_v->current_project.filename);
	tmpfilename = return_file(main_v->current_project.filename);

	if ((tmpfilename != NULL) && (file_exists_and_readable(tmpfilename) == 1)) {
		/* close old project first */
		project_close_cb(NULL, NULL);
		if (main_v->current_project.filename != NULL) {
			DEBUG_MSG("project_open, the old project isn't closed !!!!\n");
			/* TODO: statusbar message needed here !!!!!!!!! */
			goto out_free;
		}

		main_v->current_project.filename = g_strdup(tmpfilename);
		project_from_file();
	} else {
		DEBUG_MSG("project_open, filename not readable\n");
		/* TODO: statusbar message needed here !!!!!!!!! */
	}
  out_free:
	if (tmpfilename != NULL)
		g_free(tmpfilename);
}

void project_close_cb(GtkWidget * widget, gpointer data)
{
	if (main_v->current_project.filename != NULL) {
		project_to_file();
	}
	project_empty();
}

void project_save_cb(GtkWidget * widget, gpointer data)
{

	if (main_v->current_project.filename == NULL) {
		project_save_as_cb(NULL, NULL);
	} else {
		project_to_file();
	}
}

void project_save_as_cb(GtkWidget * widget, gpointer data)
{
	gchar *tmpfilename;

	/* change dir into project dir */
	tmpfilename = g_strconcat(g_get_home_dir(), "/.bluefish/projects/", NULL);
	DEBUG_MSG("project_save_as, change_dir(%s)\n", tmpfilename);
	change_dir(tmpfilename);
	g_free(tmpfilename);

	tmpfilename = return_file(main_v->current_project.filename);
	DEBUG_MSG("project_save_as, tmpfilename=%s\n", tmpfilename);
	if (tmpfilename != NULL) {
		g_free(main_v->current_project.filename);
		main_v->current_project.filename = tmpfilename;
		DEBUG_MSG("project_save_as, main_v->current_project.filename=%s\n", main_v->current_project.filename);
		project_to_file();
	} else {
		/*statusbar message needed !!!!!!!!!!!!!!!!!!!!! */
	}
}
