/*
 * 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_macro_editor_advanced_table.h"
#include "roccat_macro_editor_advanced_list_store.h"
#include "roccat_dscale.h"
#include "roccat_ruler.h"
#include "g_roccat_helper.h"
#include "gtk_roccat_helper.h"
#include <stdlib.h>

#define ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_TYPE, RoccatMacroEditorAdvancedTableClass))
#define IS_ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_TYPE))
#define ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_TYPE, RoccatMacroEditorAdvancedTablePrivate))

typedef struct _RoccatMacroEditorAdvancedTableClass RoccatMacroEditorAdvancedTableClass;
typedef struct _AbsoluteKeystroke AbsoluteKeystroke;

struct _RoccatMacroEditorAdvancedTableClass {
	GtkTableClass parent_class;
};

struct _AbsoluteKeystroke {
	guint key;
	guint action;
	GtkLabel *label;
	GtkSpinButton *lower;
	GtkSpinButton *upper;
	RoccatDScale *dscale;
};

struct _RoccatMacroEditorAdvancedTablePrivate {
	RoccatMacroEditorAdvancedListStore *store;
};

G_DEFINE_TYPE(RoccatMacroEditorAdvancedTable, roccat_macro_editor_advanced_table, GTK_TYPE_TABLE);

enum {
	ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_LABEL_COLUMN,
	ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_LOWER_COLUMN,
	ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_SCALE_COLUMN,
	ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_UPPER_COLUMN,
	ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_N_COLUMNS,
};

static void table_add_header_row(RoccatMacroEditorAdvancedTable *table) {
	GtkWidget *ruler;
	ruler = roccat_ruler_new();
	g_object_set(G_OBJECT(ruler),
			"min", 0.0,
			"interval", 1.0,
			NULL);

	gtk_table_attach(GTK_TABLE(table), ruler,
			ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_SCALE_COLUMN, ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_SCALE_COLUMN + 1,
			0, 1,
			GTK_EXPAND | GTK_FILL, 0,
			0, 0);
	gtk_widget_show(ruler);
}

static void set_ruler_max(RoccatMacroEditorAdvancedTable *macro_editor_advanced_table, gdouble max) {
	GList *children;
	GList *element;

	children = gtk_container_get_children(GTK_CONTAINER(macro_editor_advanced_table));
	for (element = children; element; element = g_list_next(element)) {
		if (IS_ROCCAT_RULER(element->data)) {
			roccat_ruler_set_max(element->data, max);
			/* There is only one ruler */
			break;
		}
	}
	g_list_free(children);
}

static void prepare_table(RoccatMacroEditorAdvancedTable *table) {
	table_add_header_row(table);
	roccat_macro_editor_advanced_list_store_set_all_max(table->priv->store, 0);
}

static void empty_changed_cb(RoccatMacroEditorAdvancedListStore *macro_editor_advanced_list_store, gpointer user_data) {
	RoccatMacroEditorAdvancedTable *macro_editor_advanced_table = ROCCAT_MACRO_EDITOR_ADVANCED_TABLE(user_data);
	if (roccat_macro_editor_advanced_list_store_empty(macro_editor_advanced_list_store)) {
		gtk_roccat_table_clear(GTK_TABLE(macro_editor_advanced_table));
		prepare_table(macro_editor_advanced_table);
	}
}

static void max_changed_cb(RoccatMacroEditorAdvancedListStore *macro_editor_advanced_list_store, gpointer user_data) {
	RoccatMacroEditorAdvancedTable *macro_editor_advanced_table = ROCCAT_MACRO_EDITOR_ADVANCED_TABLE(user_data);
	gdouble max;

	max = roccat_macro_editor_advanced_list_store_get_all_max(macro_editor_advanced_list_store);
	set_ruler_max(macro_editor_advanced_table, max);
}

static void keypress_added_cb(RoccatMacroEditorAdvancedListStore *store, GtkTreeIter *iter, gpointer user_data) {
	RoccatMacroEditorAdvancedTable *macro_editor_advanced_table = ROCCAT_MACRO_EDITOR_ADVANCED_TABLE(user_data);
	GtkTable *table = GTK_TABLE(macro_editor_advanced_table);
	guint top_attach;
	GtkWidget *label;
	GtkWidget *lower;
	GtkWidget *upper;
	GtkWidget *scale;

#if (GTK_CHECK_VERSION(2, 22, 0))
	gtk_table_get_size(GTK_TABLE(macro_editor_advanced_table), &top_attach, NULL);
#else
	g_object_get(G_OBJECT(macro_editor_advanced_table), "n-rows", &top_attach, NULL);
#endif

	label = roccat_macro_editor_advanced_list_store_get_label_widget(store, iter);
	lower = roccat_macro_editor_advanced_list_store_get_lower_widget(store, iter);
	upper = roccat_macro_editor_advanced_list_store_get_upper_widget(store, iter);
	scale = roccat_macro_editor_advanced_list_store_get_scale_widget(store, iter);

	gtk_table_attach(table, label,
			ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_LABEL_COLUMN, ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_LABEL_COLUMN + 1,
			top_attach, top_attach + 1,
			0, 0,
			0, 0);
	gtk_widget_show(label);

	gtk_table_attach(table, lower,
			ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_LOWER_COLUMN, ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_LOWER_COLUMN + 1,
			top_attach, top_attach + 1,
			0, 0,
			0, 0);
	gtk_widget_show(lower);

	gtk_table_attach(table, upper,
			ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_UPPER_COLUMN, ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_UPPER_COLUMN + 1,
			top_attach, top_attach + 1,
			0, 0,
			0, 0);
	gtk_widget_show(upper);

	gtk_table_attach(table, scale,
			ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_SCALE_COLUMN, ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_SCALE_COLUMN + 1,
			top_attach, top_attach + 1,
			GTK_EXPAND | GTK_FILL, 0,
			0, 0);
	gtk_widget_show(scale);
}

GtkWidget *roccat_macro_editor_advanced_table_new(RoccatMacroEditorAdvancedListStore *store) {
	RoccatMacroEditorAdvancedTable *macro_editor_advanced_table;

	macro_editor_advanced_table = g_object_new(ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_TYPE,
			"n-columns", ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_N_COLUMNS,
			"n-rows", 1,
			"homogeneous", FALSE,
			NULL);

	g_object_ref(store);
	macro_editor_advanced_table->priv->store = store;
	g_signal_connect(G_OBJECT(store), "max-changed", G_CALLBACK(max_changed_cb), macro_editor_advanced_table);
	g_signal_connect(G_OBJECT(store), "keypress-added", G_CALLBACK(keypress_added_cb), macro_editor_advanced_table);
	g_signal_connect(G_OBJECT(store), "empty-changed", G_CALLBACK(empty_changed_cb), macro_editor_advanced_table);

	prepare_table(macro_editor_advanced_table);

	return GTK_WIDGET(macro_editor_advanced_table);
}

static void roccat_macro_editor_advanced_table_init(RoccatMacroEditorAdvancedTable *macro_editor_advanced_table) {
	RoccatMacroEditorAdvancedTablePrivate *priv = ROCCAT_MACRO_EDITOR_ADVANCED_TABLE_GET_PRIVATE(macro_editor_advanced_table);
	macro_editor_advanced_table->priv = priv;
}

static void roccat_macro_editor_advanced_table_finalize(GObject *object) {
	RoccatMacroEditorAdvancedTablePrivate *priv = ROCCAT_MACRO_EDITOR_ADVANCED_TABLE(object)->priv;
	g_object_unref(priv->store);
	G_OBJECT_CLASS(roccat_macro_editor_advanced_table_parent_class)->finalize(object);
}

static void roccat_macro_editor_advanced_table_class_init(RoccatMacroEditorAdvancedTableClass *klass) {
	GObjectClass *gobject_class;

	gobject_class = G_OBJECT_CLASS(klass);

	gobject_class->finalize = roccat_macro_editor_advanced_table_finalize;

	g_type_class_add_private(klass, sizeof(RoccatMacroEditorAdvancedTablePrivate));
}
