/*
 * draw.c
 *
 * Vykreslovani hraci plochy
 *
 * Usporadani objektu na hraci plose:
 *  0:		pozadi
 *  2-99:	kurzory
 *  100-499:	figurky
 *  500:	policka
 *
 */


#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define _GNU_SOURCE
#include <unistd.h>

#include "draw.h"
#include "support.h"
#include "gui.h"

#define DEBUG 		0
#include "debug.h"


#define MAX_IMAGE	1024
#define MAX_OBJECT	1024


static struct s_image {
	char *file;
	GdkPixbuf *pixbuf;
} image[MAX_IMAGE];

static struct s_object {
	int exists;
	int x, y, height, width;
	int image;
} object[MAX_OBJECT];

static int board_height = 512, board_width = 512;

GdkPixbuf *draw_board = NULL;

int draw_image_load (const char *dir, const char *file, int id) {
	GError *error = NULL;
	GtkWidget *dialog;
	char *filename = NULL;
	const int cwd_len = 512;
	char cwd[512];

	assert(dir != NULL);
	assert(file != NULL);
	assert(id >= 0 && id < MAX_IMAGE);
	
	filename = (char*) malloc(strlen(dir) + strlen(file) + 3);	/* lomitko + '\0' */
	if (filename == NULL) {
		perror("malloc");
		return 0;
	}
	strcpy(filename, dir);
	strcat(filename, file);
	
	DBG_MSG(6, "draw_image_load: \"%s\" -> %d", filename, id);
	
	draw_image_remove(id);
	
	if (!(image[id].pixbuf = gdk_pixbuf_new_from_file(filename, &error))) {
		dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
				GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
				GTK_MESSAGE_ERROR,
				GTK_BUTTONS_OK,
				_("Nepovedlo se načíst obrázek"));
		gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
				_("%s\npracovní adresář: %s"),
				error->message, getcwd(cwd, cwd_len));
		gtk_dialog_run (GTK_DIALOG (dialog));
		gtk_widget_destroy (dialog);
		free(filename);
		return 0;
	}

	image[id].file = filename;

	return 1;
}


void draw_image_remove (int id) {
	DBG_MSG(6, "draw_image_remove %d", id);
	assert(id >= 0 && id < MAX_IMAGE);
	if (image[id].pixbuf) {
		DBG_MSG(10, "draw_image_remove: pixbuf = %p", image[id].pixbuf);
		gdk_pixbuf_unref(image[id].pixbuf);
		image[id].pixbuf = NULL;
	}
	
	if (image[id].file) {
		DBG_MSG(10, "draw_image_remove: file = %p", image[id].file);
		free(image[id].file);
		image[id].file = NULL;
	}
	DBG_MSG(8, "draw_image_remove %d done.", id);
}



int draw_object_add (int object_id, int image_id, int x, int y, int height, int width) {
	DBG_MSG(6, "draw_object_add: %d %d at [ %d, %d ], size %d x %d",
			object_id, image_id, x, y, height, width);
	assert(object_id >= 0 && object_id < MAX_OBJECT);
	assert(image_id >= 0 && image_id < MAX_IMAGE);
	
	if (image[image_id].pixbuf || (image_id == -1 && height > 0 && width > 0)) {
		object[object_id].exists = 1;
		object[object_id].x = x;
		object[object_id].y = y;
		object[object_id].image = image_id;
		object[object_id].width = width > 0 ? width : gdk_pixbuf_get_width(image[image_id].pixbuf);
		object[object_id].height = height > 0 ? height : gdk_pixbuf_get_height(image[image_id].pixbuf);
		
		DBG_MSG(6, "draw_object_add: x = %d, y = %d, image = %d, width = %d, height = %d",
				object[object_id].x,
				object[object_id].y,
				object[object_id].image,
				object[object_id].width,
				object[object_id].height);

		/* objekt s id == 0 je pozadi, podle nej se urci velikost plochy */
		if (object_id == 0) {
			board_width = object[object_id].width;
			board_height = object[object_id].height;
			if (draw_board)
				gdk_pixbuf_unref(draw_board);
			draw_board = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
					board_width, board_height);
			gtk_widget_set_size_request (lookup_widget(main_window, "desk_drawingarea"),
					board_width, board_height);
			gtk_widget_set_sensitive(lookup_widget(main_window, "desk_drawingarea"), TRUE);
		}
		return 1;
	} else {
		return 0;
	}
}


void draw_object_delete (int object_id) {
	DBG_MSG(6, "draw_object_delete: %d", object_id);
	assert(object_id >= 0 && object_id < MAX_OBJECT);
	object[object_id].exists = 0;
}


void draw_object_move (int object_id, int x, int y) {
	DBG_MSG(6, "draw_object_move: %d to [ %d, %d ]", object_id, x, y);
	assert(object_id >= 0 && object_id < MAX_OBJECT);
	object[object_id].x = x;
	object[object_id].y = y;
}


void draw_init (void) {
	DBG_MSG(6, "draw_init");
	bzero(image, sizeof(struct s_image) * MAX_IMAGE);
	bzero(object, sizeof(struct s_object) * MAX_OBJECT);
	gtk_widget_set_sensitive(lookup_widget(main_window, "desk_drawingarea"), FALSE);
}


void draw_remove_all (void) {
	int i;

	DBG_MSG(6, "draw_remove_all");
	for (i = 0; i < MAX_IMAGE; i++) {
		if (image[i].pixbuf || image[i].file)
			draw_image_remove(i);
	}
	draw_init();
}


void draw_all(void) {
	int i;
	static GtkWidget *da = NULL, *af = NULL, *nb = NULL, *di = NULL;
	static int hidden = 1;

	DBG_MSG(6, "draw_all");

	/* lookup optimization */
	if (!da) da = lookup_widget(main_window, "desk_drawingarea");
	if (!af) af = lookup_widget(main_window, "desk_aspectframe");
	if (!nb) nb = lookup_widget(main_window, "main_notebook");
	if (!di) di = lookup_widget(main_window, "desk_label_image");

	
	if (image[object[0].image].pixbuf == NULL) {
		/* neexistuje pozadi -> nic nekreslime */
		gtk_widget_hide(af);
		hidden = 1;
	} else {
		/* nejdrive pozadi, kterym preplacnem vsecko stare */
		DBG_MSG(8, "drawing background (%d x %d)...", board_height, board_width);
		if (hidden) {
			gtk_widget_show(af);
			hidden = 0;
		}
		
		gdk_pixbuf_copy_area(image[object[0].image].pixbuf, 0, 0, board_width, board_height, draw_board, 0, 0);
		
		for (i = 1; i < MAX_OBJECT; i++) {
			if (object[i].exists && object[i].image >= 0) {
				DBG_MSG(8, "drawing object %d at [ %d, %d ]...", i, object[i].x, object[i].y);
				gdk_pixbuf_composite (image[object[i].image].pixbuf, draw_board,
						object[i].x, object[i].y,
						gdk_pixbuf_get_height(image[object[i].image].pixbuf),
						gdk_pixbuf_get_width(image[object[i].image].pixbuf),
						object[i].x, object[i].y,
						1, 1, GDK_INTERP_NEAREST, 255);
			}
		}
		
		gtk_widget_queue_draw (da);
	}
	
	if (gtk_notebook_get_current_page(GTK_NOTEBOOK(nb)) != 0)
		gtk_widget_show(di);
}

int draw_get_object_by_xy (int x, int y) {
	int i;

	for (i = MAX_OBJECT - 1; i >= 0; i--) {
		if (object[i].exists) {
			DBG_MSG(8, "draw_get_object_by_xy: Checking object %d at %d, %d (%d x %d)",
					i, object[i].x, object[i].y, object[i].width, object[i].height);
			if (object[i].x < x && object[i].y < y
					&& object[i].x + object[i].width > x
					&& object[i].y + object[i].height > y)
			{
				DBG_MSG(5, "draw_get_object_by_xy: Found object %d", i);
				return i;
			}
		}
	}
	DBG_MSG(5, "draw_get_object_by_xy: No object found");
	return -1;
	
}


/* vim:set encoding=utf8: */

