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

#define ROCCAT_COLOR_PALETTE_BUTTON_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), ROCCAT_COLOR_PALETTE_BUTTON_TYPE, RoccatColorPaletteButtonPrivate))

struct _RoccatColorPaletteButtonPrivate {
	GtkDialog *palette_dialog;
	gint actual_index;
};

enum {
	PROP_0,
	PROP_INDEX,
};

G_DEFINE_TYPE(RoccatColorPaletteButton, roccat_color_palette_button, ROCCAT_COLOR_BUTTON_TYPE);

static void button_clicked_cb(RoccatColorPaletteButton *color_palette_button, gpointer user_data) {
	RoccatColorPaletteButtonPrivate *priv = color_palette_button->priv;

	g_assert(priv->palette_dialog);
	
	if (gtk_dialog_run(priv->palette_dialog) == GTK_RESPONSE_ACCEPT)
		roccat_color_palette_button_set_index(color_palette_button,
				roccat_color_palette_dialog_get_index(ROCCAT_COLOR_PALETTE_DIALOG(priv->palette_dialog)));
	gtk_widget_hide(GTK_WIDGET(priv->palette_dialog));
}

void roccat_color_palette_button_set_colors(RoccatColorPaletteButton *color_palette_button, GdkColor const *colors, size_t length) {
	RoccatColorPaletteButtonPrivate *priv = color_palette_button->priv;
	if (priv->palette_dialog)
		gtk_widget_destroy(GTK_WIDGET(priv->palette_dialog));
	priv->palette_dialog = GTK_DIALOG(roccat_color_palette_dialog_new(NULL, colors, length));
}

GtkWidget *roccat_color_palette_button_new(void) {
	return GTK_WIDGET(g_object_new(ROCCAT_COLOR_PALETTE_BUTTON_TYPE, NULL));
}

gint roccat_color_palette_button_get_index(RoccatColorPaletteButton const *color_palette_button) {
	return color_palette_button->priv->actual_index;
}

void roccat_color_palette_button_set_index(RoccatColorPaletteButton *color_palette_button, gint index) {
	RoccatColorPaletteButtonPrivate *priv = color_palette_button->priv;
	GdkColor color;

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

	if (priv->palette_dialog &&
			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(color_palette_button), &color);
}

static void roccat_color_palette_button_set_property(GObject *object, guint prop_id, GValue const *value, GParamSpec *pspec) {
	RoccatColorPaletteButton *color_palette_button = ROCCAT_COLOR_PALETTE_BUTTON(object);

	switch(prop_id) {
	case PROP_INDEX:
		roccat_color_palette_button_set_index(color_palette_button, g_value_get_int(value));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
	}
}

static void roccat_color_palette_button_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
	RoccatColorPaletteButton *color_palette_button = ROCCAT_COLOR_PALETTE_BUTTON(object);

	switch(prop_id) {
	case PROP_INDEX:
		g_value_set_int(value, roccat_color_palette_button_get_index(color_palette_button));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
	}
}

static void roccat_color_palette_button_init(RoccatColorPaletteButton *color_palette_button) {
	RoccatColorPaletteButtonPrivate *priv = ROCCAT_COLOR_PALETTE_BUTTON_GET_PRIVATE(color_palette_button);

	color_palette_button->priv = priv;
	priv->palette_dialog = NULL;
	
	g_signal_connect(G_OBJECT(color_palette_button), "clicked", G_CALLBACK(button_clicked_cb), NULL);
}

static void roccat_color_palette_button_finalize(GObject *object) {
	RoccatColorPaletteButtonPrivate *priv = ROCCAT_COLOR_PALETTE_BUTTON(object)->priv;
	if (priv->palette_dialog)
		gtk_widget_destroy(GTK_WIDGET(priv->palette_dialog));
	G_OBJECT_CLASS(roccat_color_palette_button_parent_class)->finalize(object);
}

static void roccat_color_palette_button_class_init(RoccatColorPaletteButtonClass *klass) {
	GObjectClass *gobject_class;

	gobject_class = (GObjectClass*)klass;

	gobject_class->set_property = roccat_color_palette_button_set_property;
	gobject_class->get_property = roccat_color_palette_button_get_property;
	gobject_class->finalize = roccat_color_palette_button_finalize;

	g_type_class_add_private(klass, sizeof(RoccatColorPaletteButtonPrivate));

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

	g_object_class_install_property(gobject_class, PROP_INDEX,
			g_param_spec_int("index",
					"index",
					"Index of selected color",
					-1, G_MAXINT, -1,
					G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
}
