/*
 *  JoeyDev
 *  Copyright (C) 2018-2023 Scott Duensing <scott@kangaroopunch.com>
 *
 *  This software is provided 'as-is', without any express or implied
 *  warranty.  In no event will the authors be held liable for any damages
 *  arising from the use of this software.
 *
 *  Permission is granted to anyone to use this software for any purpose,
 *  including commercial applications, and to alter it and redistribute it
 *  freely, subject to the following restrictions:
 *
 *  1. The origin of this software must not be misrepresented; you must not
 *     claim that you wrote the original software. If you use this software
 *     in a product, an acknowledgment in the product documentation would be
 *     appreciated but is not required.
 *  2. Altered source versions must be plainly marked as such, and must not be
 *     misrepresented as being the original software.
 *  3. This notice may not be removed or altered from any source distribution.
*/


#include "common.h"
#include "palette.h"


typedef struct PaletteDialogDataS {
	GtkWidget     *drawingArea;
	GtkAdjustment *adjustmentRed;
	GtkAdjustment *adjustmentGreen;
	GtkAdjustment *adjustmentBlue;
	GtkWidget     *scaleRed;
	GtkWidget     *scaleGreen;
	GtkWidget     *scaleBlue;
} PaletteDialogDataT;


EVENT  gboolean paletteDialogClose(GtkWidget *widget, GdkEvent *event, gpointer userData);
EVENT  gboolean paletteDialogDraw(GtkWidget *widget, cairo_t *cr, gpointer userData);
EVENT  void     paletteValueChanged(GtkRange *widget, gpointer userData);


EVENT gboolean paletteDialogClose(GtkWidget *widget, GdkEvent *event, gpointer userData) {
	PaletteDialogDataT *self = g_object_get_data(G_OBJECT(widget), "paletteData");

	(void)event;
	(void)userData;

	DEL(self);

	return FALSE;
}


EVENT gboolean paletteDialogDraw(GtkWidget *widget, cairo_t *cr, gpointer userData) {
	PaletteDialogDataT *self = (PaletteDialogDataT *)userData;
	double              scale = 1.0/16.0;
	double              r;
	double              g;
	double              b;

	(void)widget;

	r = gtk_adjustment_get_value(self->adjustmentRed);
	g = gtk_adjustment_get_value(self->adjustmentGreen);
	b = gtk_adjustment_get_value(self->adjustmentBlue);

	cairo_set_source_rgb(cr, r * scale, g * scale, b * scale);
	cairo_paint(cr);

	return FALSE;
}


EVENT void paletteValueChanged(GtkRange *widget, gpointer userData) {
	PaletteDialogDataT *self = (PaletteDialogDataT *)userData;

	(void)widget;

	// Refresh widget.
	gtk_widget_queue_draw(self->drawingArea);
}


void palette_dialog_get_color(GtkWidget *paletteDialog, unsigned char *r, unsigned char *g, unsigned char *b) {
	PaletteDialogDataT *self = g_object_get_data(G_OBJECT(paletteDialog), "paletteData");

	*r = (int)gtk_adjustment_get_value(self->adjustmentRed);
	*g = (int)gtk_adjustment_get_value(self->adjustmentGreen);
	*b = (int)gtk_adjustment_get_value(self->adjustmentBlue);
}


GtkWidget *palette_dialog_new(GtkWidget *parent, char *title, unsigned char r, unsigned char g, unsigned char b) {
	GtkWidget          *dialog;
	GtkWidget          *contentArea;
	PaletteDialogDataT *self;
	GtkWidget          *vbox;
	GtkWidget          *grid;
	GtkWidget          *labelRed;
	GtkWidget          *labelGreen;
	GtkWidget          *labelBlue;

	self = NEW(PaletteDialogDataT);

	vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
	gtk_box_set_spacing(GTK_BOX(vbox), 10);

	self->drawingArea = gtk_drawing_area_new();
	gtk_widget_set_size_request(self->drawingArea, 128, 64);
	g_signal_connect(G_OBJECT(self->drawingArea), "draw", G_CALLBACK(paletteDialogDraw), self);

	grid = gtk_grid_new();
	gtk_grid_set_column_spacing(GTK_GRID(grid), 10);
	gtk_grid_set_row_spacing(GTK_GRID(grid), 10);

	labelRed   = gtk_label_new("Red:");
	labelGreen = gtk_label_new("Green:");
	labelBlue  = gtk_label_new("Blue:");
	gtk_widget_set_halign(labelRed,   GTK_ALIGN_END);
	gtk_widget_set_halign(labelGreen, GTK_ALIGN_END);
	gtk_widget_set_halign(labelBlue,  GTK_ALIGN_END);

	self->adjustmentRed   = gtk_adjustment_new((double)r, 0.0, 15.0, 1.0, 4.0, 0.00);
	self->adjustmentGreen = gtk_adjustment_new((double)g, 0.0, 15.0, 1.0, 4.0, 0.00);
	self->adjustmentBlue  = gtk_adjustment_new((double)b, 0.0, 15.0, 1.0, 4.0, 0.00);

	self->scaleRed   = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, self->adjustmentRed);
	self->scaleGreen = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, self->adjustmentGreen);
	self->scaleBlue  = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, self->adjustmentBlue);
	gtk_scale_set_draw_value(GTK_SCALE(self->scaleRed),   FALSE);
	gtk_scale_set_draw_value(GTK_SCALE(self->scaleGreen), FALSE);
	gtk_scale_set_draw_value(GTK_SCALE(self->scaleBlue),  FALSE);
	gtk_range_set_round_digits(GTK_RANGE(self->scaleRed),   0);
	gtk_range_set_round_digits(GTK_RANGE(self->scaleGreen), 0);
	gtk_range_set_round_digits(GTK_RANGE(self->scaleBlue),  0);
	gtk_widget_set_hexpand(self->scaleRed,   TRUE);
	gtk_widget_set_hexpand(self->scaleGreen, TRUE);
	gtk_widget_set_hexpand(self->scaleBlue,  TRUE);
	g_signal_connect(G_OBJECT(self->scaleRed),   "value-changed", G_CALLBACK(paletteValueChanged), self);
	g_signal_connect(G_OBJECT(self->scaleGreen), "value-changed", G_CALLBACK(paletteValueChanged), self);
	g_signal_connect(G_OBJECT(self->scaleBlue),  "value-changed", G_CALLBACK(paletteValueChanged), self);

	dialog = gtk_dialog_new_with_buttons(
			title,
			GTK_WINDOW(parent),
			GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
			"_Cancel",
			GTK_RESPONSE_CANCEL,
			"_Select",
			GTK_RESPONSE_OK,
			NULL
	);
	g_signal_connect(G_OBJECT(dialog), "destroy", G_CALLBACK(paletteDialogClose), self);
	g_object_set_data(G_OBJECT(dialog), "paletteData", self);
	contentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));

	gtk_grid_attach(GTK_GRID(grid), labelRed,         0, 0, 1, 1);
	gtk_grid_attach(GTK_GRID(grid), labelGreen,       0, 1, 1, 1);
	gtk_grid_attach(GTK_GRID(grid), labelBlue,        0, 2, 1, 1);
	gtk_grid_attach(GTK_GRID(grid), self->scaleRed,   1, 0, 1, 1);
	gtk_grid_attach(GTK_GRID(grid), self->scaleGreen, 1, 1, 1, 1);
	gtk_grid_attach(GTK_GRID(grid), self->scaleBlue,  1, 2, 1, 1);

	gtk_container_add(GTK_CONTAINER(vbox),        self->drawingArea);
	gtk_container_add(GTK_CONTAINER(vbox),        grid);
	gtk_container_add(GTK_CONTAINER(contentArea), vbox);

	gtk_widget_show_all(dialog);

	return dialog;
}
