/*
 * 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_multi_color_palette_button.h"
#include "roccat_color_palette_dialog.h"

#define ROCCAT_MULTI_COLOR_PALETTE_BUTTON_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), ROCCAT_MULTI_COLOR_PALETTE_BUTTON_TYPE, RoccatMultiColorPaletteButtonPrivate))

struct _RoccatMultiColorPaletteButtonPrivate {
	gboolean use_palette;
	GtkDialog *palette_dialog;
	GtkDialog *custom_dialog;
	gint actual_index;
	GdkColor actual_color;
};

G_DEFINE_TYPE(RoccatMultiColorPaletteButton, roccat_multi_color_palette_button, ROCCAT_COLOR_BUTTON_TYPE);

static void button_clicked_cb(RoccatMultiColorPaletteButton *multi_color_palette_button, gpointer user_data) {
	RoccatMultiColorPaletteButtonPrivate *priv = multi_color_palette_button->priv;
	GtkColorSelection *color_selection;
	GdkColor color;
	
	if (priv->use_palette) {
		if (gtk_dialog_run(priv->palette_dialog) == GTK_RESPONSE_ACCEPT)
			roccat_multi_color_palette_button_set_index(multi_color_palette_button,
					roccat_color_palette_dialog_get_index(ROCCAT_COLOR_PALETTE_DIALOG(priv->palette_dialog)));
		gtk_widget_hide(GTK_WIDGET(priv->palette_dialog));
	} else {
		color_selection = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(priv->custom_dialog)));
		gtk_color_selection_set_current_color(color_selection, &priv->actual_color);
		if (gtk_dialog_run(priv->custom_dialog) == GTK_RESPONSE_OK) {
			gtk_color_selection_get_current_color(color_selection, &color);
			roccat_multi_color_palette_button_set_color(multi_color_palette_button, &color);
		}
		gtk_widget_hide(GTK_WIDGET(priv->custom_dialog));
	}
}

GtkWidget *roccat_multi_color_palette_button_new(GdkColor const *colors, size_t length) {
	RoccatMultiColorPaletteButton *multi_color_palette_button;
	RoccatMultiColorPaletteButtonPrivate *priv;

	multi_color_palette_button = g_object_new(ROCCAT_MULTI_COLOR_PALETTE_BUTTON_TYPE, NULL);
	priv = multi_color_palette_button->priv;

	priv->palette_dialog = GTK_DIALOG(roccat_color_palette_dialog_new(NULL, colors, length));
	priv->custom_dialog = GTK_DIALOG(gtk_color_selection_dialog_new("Choose color"));

	return GTK_WIDGET(multi_color_palette_button);
}

gboolean roccat_multi_color_palette_button_get_use_palette(RoccatMultiColorPaletteButton *multi_color_palette_button) {
	return multi_color_palette_button->priv->use_palette;
}

static void update(RoccatMultiColorPaletteButton *multi_color_palette_button) {
	RoccatMultiColorPaletteButtonPrivate *priv = multi_color_palette_button->priv;
	GdkColor color;

	if (priv->use_palette) {
		if (roccat_color_palette_dialog_get_color_for_index(ROCCAT_COLOR_PALETTE_DIALOG(priv->palette_dialog), priv->actual_index, &color))
			roccat_color_button_set_color(ROCCAT_COLOR_BUTTON(multi_color_palette_button), &color);
	} else
		roccat_color_button_set_color(ROCCAT_COLOR_BUTTON(multi_color_palette_button), &priv->actual_color);
}

void roccat_multi_color_palette_button_set_use_palette(RoccatMultiColorPaletteButton *multi_color_palette_button, gboolean use_palette) {
	multi_color_palette_button->priv->use_palette = use_palette;
	update(multi_color_palette_button);
}

void roccat_multi_color_palette_button_get_color(RoccatMultiColorPaletteButton *multi_color_palette_button, GdkColor *color) {
	*color = multi_color_palette_button->priv->actual_color;
}

void roccat_multi_color_palette_button_set_color(RoccatMultiColorPaletteButton *multi_color_palette_button, GdkColor const *color) {
	RoccatMultiColorPaletteButtonPrivate *priv = multi_color_palette_button->priv;

	if (!gdk_color_equal(color, &priv->actual_color)) {
		priv->actual_color = *color;
		g_signal_emit_by_name((gpointer)multi_color_palette_button, "value-changed");
	}

	update(multi_color_palette_button);
}

gint roccat_multi_color_palette_button_get_index(RoccatMultiColorPaletteButton const *multi_color_palette_button) {
	return multi_color_palette_button->priv->actual_index;
}

void roccat_multi_color_palette_button_set_index(RoccatMultiColorPaletteButton *multi_color_palette_button, gint index) {
	RoccatMultiColorPaletteButtonPrivate *priv = multi_color_palette_button->priv;

	if (index != priv->actual_index) {
		priv->actual_index = index;
		g_signal_emit_by_name((gpointer)multi_color_palette_button, "value-changed");
	}
	
	update(multi_color_palette_button);
}

static void roccat_multi_color_palette_button_init(RoccatMultiColorPaletteButton *multi_color_palette_button) {
	RoccatMultiColorPaletteButtonPrivate *priv = ROCCAT_MULTI_COLOR_PALETTE_BUTTON_GET_PRIVATE(multi_color_palette_button);

	multi_color_palette_button->priv = priv;
	priv->use_palette = FALSE;

	g_signal_connect(G_OBJECT(multi_color_palette_button), "clicked", G_CALLBACK(button_clicked_cb), NULL);
}

static void roccat_multi_color_palette_button_finalize(GObject *object) {
	RoccatMultiColorPaletteButtonPrivate *priv = ROCCAT_MULTI_COLOR_PALETTE_BUTTON(object)->priv;
	gtk_widget_destroy(GTK_WIDGET(priv->palette_dialog));
	gtk_widget_destroy(GTK_WIDGET(priv->custom_dialog));
	G_OBJECT_CLASS(roccat_multi_color_palette_button_parent_class)->finalize(object);
}

static void roccat_multi_color_palette_button_class_init(RoccatMultiColorPaletteButtonClass *klass) {
	GObjectClass *gobject_class = (GObjectClass*)klass;

	gobject_class->finalize = roccat_multi_color_palette_button_finalize;

	g_type_class_add_private(klass, sizeof(RoccatMultiColorPaletteButtonPrivate));

	g_signal_new("value-changed",
			G_TYPE_FROM_CLASS(klass),
			G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
			G_STRUCT_OFFSET(RoccatMultiColorPaletteButtonClass, value_changed),
			NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}
