/*
 * draw.c
 *
 * Copyright (C) 2005-2007  Josef Kufner <jk@myserver.cz>
 * 
 * This program 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.
 *
 * This program 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.
 *
 *
 *
 * Object with id 0 is background. Objects are drawn in order by their ids.
 *
 */


#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 "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 GtkWidget *draw_widget = 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) {
			gtk_widget_set_size_request(draw_widget, object[0].width, object[0].height);
		}
		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 (GtkWidget *drawing_area)
{
	DBG_MSG(6, "draw_init");
	assert(drawing_area != NULL);
	draw_widget = drawing_area;
	bzero(image, sizeof(struct s_image) * MAX_IMAGE);
	bzero(object, sizeof(struct s_object) * MAX_OBJECT);
	gtk_widget_set_size_request (draw_widget, 1, 1);
}


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(draw_widget);
}


void draw_all(void) {
	gtk_widget_queue_draw (draw_widget);
	gui_page_notify(GUI_PAGE_BOARD);
}

void draw_all_real(void) {
	int i;
	DBG_MSG(6, "draw_all");

	if (image[object[0].image].pixbuf != NULL) {
		DBG_MSG(8, "drawing background...");
		gdk_draw_pixbuf(draw_widget->window, NULL, image[object[0].image].pixbuf,
				0, 0, 0, 0, -1, -1,
				GDK_RGB_DITHER_NORMAL, 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_draw_pixbuf(draw_widget->window, NULL, image[object[i].image].pixbuf,
						0, 0, object[i].x, object[i].y, -1, -1,
						GDK_RGB_DITHER_NORMAL, 0, 0);
			}
		}
	}
}

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: */

