/*
    Copyright (C) 2008-2010 Stefan Haller

    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 3 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, see <http://www.gnu.org/licenses/>.
*/

#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <libintl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#include "../misc/general.h"
#include "desktopnova-profiles.h"
#include "desktopnova.h"

#define _(message) dgettext(GETTEXT_PACKAGE, message)

GtkWidget * profile_window;
GtkWidget * vbox_all;
GtkWidget * label;
GtkWidget * hbox_list;
GtkWidget * scrolled_tree_profiles;
GtkWidget * tree_profiles;
GtkWidget * vbox_buttons;
GtkWidget * button_add;
GtkWidget * button_remove;
GtkWidget * button_rename;
GtkWidget * button_clear;
GtkWidget * hseparator;
GtkWidget * button_box;
GtkWidget * button_ok;
GtkWidget * button_cancel;

GtkListStore * list_settings_profiles;
GtkCellRenderer * renderer_name;
GtkTreeViewColumn * column_name;

enum
{
	COLUMN_NAME,
	COLUMN_STORE,
	N_COLUMNS
};

/* list functions */

void free_profile_settings(struct ProfileSettings * profile_settings)
{

	struct ProfileItem * item = profile_settings->profile_items;
	struct ProfileItem * item_old;

	while (item != NULL)
	{
		g_free(item->name);
		item_old = item;
		item = item->next;
		g_free(item_old);
	}

	profile_settings->succeed = FALSE;
	profile_settings->profile_items = NULL;
}

/* signal handling */

void button_profile_cancel_clicked(GtkButton * button, gpointer user_data)
{
	gtk_widget_destroy(profile_window);
}

void button_profile_ok_clicked(GtkButton * button, gpointer user_data)
{
	struct ProfileSettings profile_settings;
	GtkTreeIter iter;
	GValue value = {0, };
	struct ProfileItem * item = NULL;

	profile_settings.succeed = TRUE;
	profile_settings.profile_items = NULL;

	gboolean result = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list_settings_profiles),
	                                                &iter);
	while (result)
	{
		if (item == NULL)
		{
			profile_settings.profile_items = g_new(struct ProfileItem, 1);
			item =  profile_settings.profile_items;
		}
		else
		{
			item->next = g_new(struct ProfileItem, 1);
			item = item->next;
		}

		item->next = NULL;

		gtk_tree_model_get_value(GTK_TREE_MODEL(list_settings_profiles), &iter, COLUMN_NAME, &value);
		item->name = g_strdup(g_value_get_string(&value));
		g_value_unset(&value);

		gtk_tree_model_get_value(GTK_TREE_MODEL(list_settings_profiles), &iter, COLUMN_STORE, &value);
		item->store = g_value_get_pointer(&value);
		g_value_unset(&value);

		result = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_settings_profiles), &iter);
	}

	gtk_widget_destroy(profile_window);
	callback_settings_changed(&profile_settings);
	free_profile_settings(&profile_settings);
}

void button_profile_add_clicked(GtkButton * button, gpointer user_data)
{
	GtkWidget * dialog = gtk_dialog_new_with_buttons(_("Create new profile"),
	                     GTK_WINDOW(profile_window),
	                     GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
	                     GTK_STOCK_OK,
	                     GTK_RESPONSE_OK,
	                     GTK_STOCK_CANCEL,
	                     GTK_RESPONSE_CANCEL,
	                     NULL);
	gtk_container_set_border_width(GTK_CONTAINER(dialog), 6);
	gtk_window_set_default_size(GTK_WINDOW(dialog), 350, 0);
	gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
	gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);

	/* gtk_dialog_get_content_area is only available with Gtk 2.14 and newer */
	//GtkWidget * content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
	GtkWidget * content_area = GTK_DIALOG(dialog)->vbox;
	gtk_box_set_spacing(GTK_BOX(content_area), 12);

	GtkWidget * label = gtk_label_new(_("Please enter the name of the new profile:"));
	gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);

	GtkWidget * entry = gtk_entry_new();
	gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);

	gtk_box_pack_start(GTK_BOX(content_area), label, FALSE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(content_area), entry, FALSE, TRUE, 0);

	gtk_widget_show_now(label);
	gtk_widget_show_now(entry);
	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
	{
		const gchar * name = gtk_entry_get_text(GTK_ENTRY(entry));
		GtkTreeIter iter;
		gboolean append = FALSE;
		gboolean done = FALSE;
		gboolean result = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list_settings_profiles),
		                                                &iter);
		while ((! done) && (result))
		{
			GtkTreeIter newiter;
			GValue value = {0, };
			gchar * current;

			gtk_tree_model_get_value(GTK_TREE_MODEL(list_settings_profiles), &iter, COLUMN_NAME, &value);
			current = g_strdup(g_value_get_string(&value));
			g_value_unset(&value);

			gboolean insert = g_strcmp0(name, current) < 0;
			g_free(current);
			if (insert)
			{
				gtk_list_store_insert_before(list_settings_profiles,
				                             &newiter,
				                             &iter);
				iter = newiter;
				done = TRUE;
				break;
			}

			result = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_settings_profiles),
			                                  &iter);
		}

		if (! done)
				append = TRUE;

		if (append)
			gtk_list_store_append(list_settings_profiles, &iter);
		gtk_list_store_set(list_settings_profiles, &iter,
		                   COLUMN_NAME, name,
		                   COLUMN_STORE, NULL,
		                   -1);
	}
	gtk_widget_destroy(dialog);
}

void button_profile_rename_clicked(GtkButton * button, gpointer user_data)
{
	GtkWidget * dialog = gtk_dialog_new_with_buttons(_("Rename profile"),
	                     GTK_WINDOW(profile_window),
	                     GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
	                     GTK_STOCK_OK,
	                     GTK_RESPONSE_OK,
	                     GTK_STOCK_CANCEL,
	                     GTK_RESPONSE_CANCEL,
	                     NULL);
	gtk_container_set_border_width(GTK_CONTAINER(dialog), 6);
	gtk_window_set_default_size(GTK_WINDOW(dialog), 350, 0);
	gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
	gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);

	/* gtk_dialog_get_content_area is only available with Gtk 2.14 and newer */
	//GtkWidget * content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
	GtkWidget * content_area = GTK_DIALOG(dialog)->vbox;
	gtk_box_set_spacing(GTK_BOX(content_area), 12);

	GtkWidget * label = gtk_label_new(_("Please enter the new name of the profile:"));
	gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);

	GtkWidget * entry = gtk_entry_new();
	gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);

	gtk_box_pack_start(GTK_BOX(content_area), label, FALSE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(content_area), entry, FALSE, TRUE, 0);

	gtk_widget_show_now(label);
	gtk_widget_show_now(entry);
	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
	{
		const gchar * name = gtk_entry_get_text(GTK_ENTRY(entry));

		GtkTreePath * path;
		GtkTreeIter iter;
		gtk_tree_view_get_cursor(GTK_TREE_VIEW(tree_profiles), &path, NULL);
		if (path != NULL)
		{
			gtk_tree_model_get_iter(GTK_TREE_MODEL(list_settings_profiles), &iter, path);
			gtk_tree_path_free(path);
			gtk_list_store_set(list_settings_profiles, &iter, COLUMN_NAME, name, -1);

			GtkTreeIter pos_iter, old_pos_iter;

			gboolean result = gtk_tree_model_get_iter_first(
			                  GTK_TREE_MODEL(list_settings_profiles),
			                  &pos_iter);
			while (result)
			{
				GValue value = {0, };
				gtk_tree_model_get_value(GTK_TREE_MODEL(list_settings_profiles), &pos_iter, COLUMN_NAME, &value);
				gchar * current = g_strdup(g_value_get_string(&value));
				g_value_unset(&value);

				gboolean move = g_strcmp0(name, current) < 0;
				g_free(current);
				if (move)
				{
					gtk_list_store_move_before(GTK_LIST_STORE(list_settings_profiles),
					                           &iter,
					                           &pos_iter);
					break;
				}

				old_pos_iter = pos_iter;
				result = gtk_tree_model_iter_next(GTK_TREE_MODEL(
				                                  list_settings_profiles),
				                                  &pos_iter);
				if (! result)
				{
					gtk_list_store_move_after(GTK_LIST_STORE(list_settings_profiles),
					                          &iter,
					                          &old_pos_iter);
				}
			}
		}
	}
	gtk_widget_destroy(dialog);
}

void button_profile_remove_clicked(GtkButton * button, gpointer user_data)
{
	GtkTreePath * path;
	GtkTreeIter iter;
	gtk_tree_view_get_cursor(GTK_TREE_VIEW(tree_profiles), &path, NULL);
	if (path != NULL)
	{
		gtk_tree_model_get_iter(GTK_TREE_MODEL(list_settings_profiles), &iter, path);
		gtk_tree_path_free(path);
		gtk_list_store_remove(list_settings_profiles, &iter);
	}
}

void button_profile_clear_clicked(GtkButton * button, gpointer user_data)
{
	gtk_list_store_clear(list_settings_profiles);
}


/* ***** */

void create_profile_settings_window()
{	
	/* create widgets */
	profile_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	label = gtk_label_new(_("<b>Profile settings:</b>"));
	vbox_all = gtk_vbox_new(FALSE, 12);
	hbox_list = gtk_hbox_new(FALSE, 12);
	list_settings_profiles = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER);
	tree_profiles = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_settings_profiles));
	g_object_unref(G_OBJECT(list_settings_profiles));
	scrolled_tree_profiles = gtk_scrolled_window_new(NULL, NULL);
	renderer_name = gtk_cell_renderer_text_new();
	column_name = gtk_tree_view_column_new_with_attributes (_("Name"), renderer_name, "text", COLUMN_NAME, NULL);
	gtk_tree_view_append_column (GTK_TREE_VIEW(tree_profiles), column_name);
	vbox_buttons = gtk_vbox_new(FALSE, 6);
	button_add = gtk_button_new_with_label(_("Add"));
	button_remove = gtk_button_new_with_label(_("Remove"));
	button_rename = gtk_button_new_with_label(_("Rename"));
	button_clear = gtk_button_new_with_label(_("Clear"));
	hseparator = gtk_hseparator_new();
	button_box = gtk_hbutton_box_new();
	button_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
	button_cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL);

	/* set up widgets */
	GTK_WIDGET_SET_FLAGS(button_ok, GTK_CAN_DEFAULT);
	gtk_window_set_modal(GTK_WINDOW(profile_window), TRUE);
	gtk_window_set_title(GTK_WINDOW(profile_window), _("Profile settings"));
	gtk_window_set_position(GTK_WINDOW(profile_window), GTK_WIN_POS_CENTER);
	gtk_window_set_default_size(GTK_WINDOW(profile_window), 300, 300);
	gtk_window_set_default(GTK_WINDOW(profile_window), button_ok);
	gtk_container_set_border_width(GTK_CONTAINER(profile_window), 12);
	gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
	gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_tree_profiles),GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(scrolled_tree_profiles), GTK_SHADOW_ETCHED_IN);
	gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END);
	gtk_box_set_spacing(GTK_BOX(button_box), 12);



	/* packing controls */
	gtk_container_add(GTK_CONTAINER(scrolled_tree_profiles), tree_profiles); 

	gtk_box_pack_start(GTK_BOX(vbox_all), label, FALSE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(vbox_all), hbox_list, TRUE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(vbox_all), hseparator, FALSE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(vbox_all), button_box, FALSE, TRUE, 0);

	gtk_box_pack_start(GTK_BOX(hbox_list), scrolled_tree_profiles, TRUE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(hbox_list), vbox_buttons, FALSE, TRUE, 0);

	gtk_box_pack_start(GTK_BOX(vbox_buttons), button_add, FALSE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(vbox_buttons), button_remove, FALSE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(vbox_buttons), button_rename, FALSE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(vbox_buttons), button_clear, FALSE, TRUE, 0);

	gtk_box_pack_start(GTK_BOX(button_box), button_cancel, FALSE, TRUE, 0);
	gtk_box_pack_start(GTK_BOX(button_box), button_ok, FALSE, TRUE, 0);

	gtk_container_add(GTK_CONTAINER(profile_window), vbox_all);

	/* connect signals */
	g_signal_connect(G_OBJECT(button_ok), "clicked", G_CALLBACK(button_profile_ok_clicked), 0);
	g_signal_connect(G_OBJECT(button_cancel), "clicked", G_CALLBACK(button_profile_cancel_clicked), 0);
	g_signal_connect(G_OBJECT(button_add), "clicked", G_CALLBACK(button_profile_add_clicked), 0);
	g_signal_connect(G_OBJECT(button_remove), "clicked", G_CALLBACK(button_profile_remove_clicked), 0);
	g_signal_connect(G_OBJECT(button_rename), "clicked", G_CALLBACK(button_profile_rename_clicked), 0);
	g_signal_connect(G_OBJECT(button_clear), "clicked", G_CALLBACK(button_profile_clear_clicked), 0);

}

void show_profile_settings(struct ProfileSettings * profile_settings)
{
	GtkTreeIter iter;
	struct ProfileItem * item;

	create_profile_settings_window();

	/* clear old list */
	gtk_list_store_clear(list_settings_profiles);

	/* fill list */
	item = profile_settings->profile_items;

	while (item != NULL)
	{
		gtk_list_store_append(list_settings_profiles, &iter);
		gtk_list_store_set(list_settings_profiles, &iter,
				COLUMN_NAME, item->name,
				COLUMN_STORE, item->store,
				-1);

		item = item->next;
	}

	gtk_widget_show_all(profile_window);
}

#undef _
