/*
 * This file is part of roccat-tools.
 *
 * roccat-tools 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.
 *
 * roccat-tools 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 roccat-tools. If not, see <http://www.gnu.org/licenses/>.
 */

#include "roccat_config_window.h"
#include "roccat_about_dialog.h"
#include "roccat_timer_editor_dialog.h"
#include "roccat_macro_editor_dialog.h"
#include "gtk_roccat_helper.h"

#define ROCCAT_CONFIG_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), ROCCAT_CONFIG_WINDOW_TYPE, RoccatConfigWindowClass))
#define IS_ROCCAT_CONFIG_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), ROCCAT_CONFIG_WINDOW_TYPE))
#define ROCCAT_CONFIG_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), ROCCAT_CONFIG_WINDOW_TYPE, RoccatConfigWindowPrivate))

typedef struct _RoccatConfigWindowClass RoccatConfigWindowClass;
typedef struct _RoccatConfigWindowPrivate RoccatConfigWindowPrivate;

struct _RoccatConfigWindow {
	GtkWindow window;
	RoccatConfigWindowPrivate *priv;
};

struct _RoccatConfigWindowClass {
	GtkWindowClass parent_class;
	void (*save_all)(RoccatConfigWindow *window);
	void (*surface_check)(RoccatConfigWindow *window);
};

struct _RoccatConfigWindowPrivate {
	GtkNotebook *notebook;
	GtkMenuBar *menu_bar;
	GtkMenu *edit_menu;
	gchar *total_device_name;
};

G_DEFINE_TYPE(RoccatConfigWindow, roccat_config_window, GTK_TYPE_WINDOW);

enum {
	SAVE_ALL,
	LAST_SIGNAL
};

static guint signals[LAST_SIGNAL] = { 0 };

GtkWidget *roccat_config_window_new(gchar const *total_device_name) {
	RoccatConfigWindow *roccat_config_window;

	roccat_config_window = g_object_new(ROCCAT_CONFIG_WINDOW_TYPE,
			"type", GTK_WINDOW_TOPLEVEL,
			NULL);

	roccat_config_window->priv->total_device_name = g_strdup(total_device_name);

	roccat_config_window_set_title_disconnected(roccat_config_window);

	return GTK_WIDGET(roccat_config_window);
}

static void menu_file_save_all_cb(GtkMenuItem *item, gpointer user_data) {
	RoccatConfigWindow *roccat_config_window = ROCCAT_CONFIG_WINDOW(user_data);
	g_signal_emit((gpointer)roccat_config_window, signals[SAVE_ALL], 0);
}

static void menu_file_quit_cb(GtkMenuItem *item, gpointer user_data) {
	RoccatConfigWindow *roccat_config_window = ROCCAT_CONFIG_WINDOW(user_data);
	GdkEvent *event;
	gboolean retval;

	/* close window like the close button has been pressed
	 * and let the client code save unsaved data
	 */
	event = gdk_event_new(GDK_DELETE);
	g_signal_emit_by_name((gpointer)roccat_config_window, "delete-event", event, &retval);
	gdk_event_free(event);
	if (!retval)
		gtk_widget_destroy(GTK_WIDGET(roccat_config_window));
}

static void menu_edit_timers_cb(GtkMenuItem *item, gpointer user_data) {
	RoccatConfigWindow *roccat_config_window = ROCCAT_CONFIG_WINDOW(user_data);
	roccat_timer_editor_dialog(GTK_WINDOW(roccat_config_window));
}

static void menu_edit_macros_cb(GtkMenuItem *item, gpointer user_data) {
	RoccatConfigWindow *roccat_config_window = ROCCAT_CONFIG_WINDOW(user_data);
	roccat_macro_editor_dialog(GTK_WINDOW(roccat_config_window));
}

static void menu_help_about_cb(GtkMenuItem *item, gpointer user_data) {
	RoccatConfigWindow *roccat_config_window = ROCCAT_CONFIG_WINDOW(user_data);
	gchar *title;

	title = g_strdup_printf("Application to manipulate profiles and settings of Roccat %s devices",
			roccat_config_window->priv->total_device_name);
	roccat_about_dialog(GTK_WINDOW(roccat_config_window), NULL, title);
	g_free(title);
}

static GtkWidget *menu_bar_new(RoccatConfigWindow *roccat_config_window) {
	RoccatConfigWindowPrivate *priv = roccat_config_window->priv;
	GtkWidget *menu_bar;
	GtkWidget *menu_item;
	GtkWidget *menu;

	menu_bar = gtk_menu_bar_new();

	menu_item = gtk_menu_item_new_with_label("File");
	menu = gtk_menu_new();
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu);
	gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_item);

	menu_item = gtk_image_menu_item_new_with_label("Store all in device");
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
	g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(menu_file_save_all_cb), roccat_config_window);

	/* separator */
	menu_item = gtk_menu_item_new();
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);

	menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
	g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(menu_file_quit_cb), roccat_config_window);


	menu_item = gtk_menu_item_new_with_label("Edit");
	priv->edit_menu = GTK_MENU(gtk_menu_new());
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), GTK_WIDGET(priv->edit_menu));
	gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_item);

	menu_item = gtk_image_menu_item_new_with_label("Macros");
	gtk_menu_shell_append(GTK_MENU_SHELL(priv->edit_menu), menu_item);
	g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(menu_edit_macros_cb), roccat_config_window);

	menu_item = gtk_image_menu_item_new_with_label("Timers");
	gtk_menu_shell_append(GTK_MENU_SHELL(priv->edit_menu), menu_item);
	g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(menu_edit_timers_cb), roccat_config_window);


	menu_item = gtk_menu_item_new_with_label("Help");
	menu = gtk_menu_new();
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu);
	gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_item);

	menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT, NULL);
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
	g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(menu_help_about_cb), roccat_config_window);

	return menu_bar;
}

static void roccat_config_window_init(RoccatConfigWindow *roccat_config_window) {
	RoccatConfigWindowPrivate *priv = ROCCAT_CONFIG_WINDOW_GET_PRIVATE(roccat_config_window);
	GtkWidget *vbox;

	roccat_config_window->priv = priv;

	gtk_window_set_default_icon_name("roccat");

	vbox = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(roccat_config_window), GTK_WIDGET(vbox));

	priv->menu_bar = GTK_MENU_BAR(menu_bar_new(roccat_config_window));
	gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(priv->menu_bar), FALSE, FALSE, 0);

	priv->notebook = GTK_NOTEBOOK(gtk_notebook_new());
	gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(priv->notebook), TRUE, TRUE, 0);

	gtk_widget_show_all(vbox);
}

static void finalize(GObject *object) {
	RoccatConfigWindow *roccat_config_window = ROCCAT_CONFIG_WINDOW(object);
	g_free(roccat_config_window->priv->total_device_name);
	G_OBJECT_CLASS(roccat_config_window_parent_class)->finalize(object);
}

static void roccat_config_window_class_init(RoccatConfigWindowClass *klass) {
	GObjectClass *gobject_class = (GObjectClass*)klass;

	gobject_class->finalize = finalize;

	g_type_class_add_private(klass, sizeof(RoccatConfigWindowPrivate));

	signals[SAVE_ALL] = g_signal_new("save-all",
			G_TYPE_FROM_CLASS(klass),
			G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
			G_STRUCT_OFFSET(RoccatConfigWindowClass, save_all),
			NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}

void roccat_config_window_append_page(RoccatConfigWindow *roccat_config_window, GtkWidget *child, GtkWidget *tab_label) {
	RoccatConfigWindowPrivate *priv = roccat_config_window->priv;

	gtk_widget_show(child);

	gtk_notebook_append_page(priv->notebook, child, tab_label);

	gtk_notebook_set_show_tabs(priv->notebook, !(gtk_notebook_get_n_pages(priv->notebook) == 1));
}

void roccat_config_window_set_tab_label_text(RoccatConfigWindow *roccat_config_window, GtkWidget *child, gchar const *text) {
	gtk_notebook_set_tab_label_text(roccat_config_window->priv->notebook, child, text);
}

static void roccat_config_window_set_title(RoccatConfigWindow *roccat_config_window, gboolean connected, gchar const *device_name) {
	gchar *title;

	title = g_strdup_printf("%s configuration - %s connected",
			roccat_config_window->priv->total_device_name,
			connected ? device_name : "no device");
	gtk_window_set_title(GTK_WINDOW(roccat_config_window), title);
	g_free(title);
}

void roccat_config_window_set_title_disconnected(RoccatConfigWindow *roccat_config_window) {
	roccat_config_window_set_title(roccat_config_window, FALSE, "");
}

void roccat_config_window_set_title_connected(RoccatConfigWindow *roccat_config_window, gchar const *device_name) {
	roccat_config_window_set_title(roccat_config_window, TRUE, device_name);
}

void roccat_config_window_menu_insert(RoccatConfigWindow *roccat_config_window, GtkMenuItem *menu_item) {
	RoccatConfigWindowPrivate *priv = roccat_config_window->priv;
	gint position;

	/* second to last */
	position = gtk_roccat_container_get_n_children(GTK_CONTAINER(priv->menu_bar)) - 1;
	if (position < 0)
		position = 0;

	gtk_menu_shell_insert(GTK_MENU_SHELL(priv->menu_bar), GTK_WIDGET(menu_item), position);
}

void roccat_config_window_edit_menu_append(RoccatConfigWindow *roccat_config_window, GtkMenuItem *menu_item) {
	RoccatConfigWindowPrivate *priv = roccat_config_window->priv;
	gtk_widget_show(GTK_WIDGET(menu_item));
	gtk_menu_shell_append(GTK_MENU_SHELL(priv->edit_menu), GTK_WIDGET(menu_item));
}
