#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#ifdef HAVE_IMLIB
# include <Imlib.h>
#endif
#include <gtk/gtk.h>

#include "imgview.h"

#include "cfg.h"
#include "edvtypes.h"
#include "edvobj.h"
#include "imbr.h"
#include "imbrtlist.h"
#include "imbrimgview.h"
#include "endeavour.h"
#include "edvutils.h"
#include "edvutilsgtk.h"
#include "edvcfglist.h"
#include "config.h"


void EDVImbrImgViewClear(edv_imbr_struct *imbr);
void EDVImbrImgViewLoad(
	edv_imbr_struct *imbr, const gchar *path, gint thumb_num
);


#define ATOI(s)         (((s) != NULL) ? atoi(s) : 0)
#define ATOL(s)         (((s) != NULL) ? atol(s) : 0)
#define ATOF(s)         (((s) != NULL) ? atof(s) : 0.0f)
#define STRDUP(s)       (((s) != NULL) ? g_strdup(s) : NULL)

#define MAX(a,b)        (((a) > (b)) ? (a) : (b))
#define MIN(a,b)        (((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
#define STRLEN(s)       (((s) != NULL) ? strlen(s) : 0)
#define STRISEMPTY(s)   (((s) != NULL) ? (*(s) == '\0') : TRUE)


/*
 *	Clears the Image Browser's ImgView.
 */
void EDVImbrImgViewClear(edv_imbr_struct *imbr)
{
	imgview_struct *iv = (imbr != NULL) ? imbr->imgview : NULL;
	if(iv == NULL)
	    return;

	ImgViewClear(iv);
}


/*
 *	Loads the image file specified by path to the Image Browser's
 *	ImgView, if thumb_num is not -1 then the thumb on the Image
 *	Browser's Thumbs List will be updated as well.
 *
 *	This function will automatically call EDVImbrImgViewClear()
 *	first.
 */
void EDVImbrImgViewLoad(
	edv_imbr_struct *imbr, const gchar *path, gint thumb_num
)
{
	gboolean need_zoom_to_fit = FALSE;
	const gchar *name;
	gint width, height, bpl;
	guint8 *data_rgba;
	GdkVisual *vis;
	GdkWindow *window;
	GtkWidget *w;
	const cfg_item_struct *cfg_list;
	imgview_image_struct *img;
	edv_core_struct *core_ptr;
	imgview_struct *iv = (imbr != NULL) ? imbr->imgview : NULL;
	if(iv == NULL)
	    return;

	/* Clear the ImgView */
	EDVImbrImgViewClear(imbr);

	core_ptr = EDV_CORE(imbr->core_ptr);
	if((core_ptr == NULL) || STRISEMPTY(path))
	    return;

	name = EDVGetPathName(path);
	cfg_list = core_ptr->cfg_list;

	/* Is the file's extension not supported by Imlib? */
	if(!EDVCheckImlibImage(core_ptr, name))
	    return;


	EDVImbrSetBusy(imbr, TRUE);

	/* Get the ImgView's view widget and window */
	w = (GtkWidget *)ImgViewGetViewWidget(iv);
	window = (w != NULL) ? w->window : NULL;
	vis = gdk_window_get_visual(window);

	/* Load the image data from the specified file */
	data_rgba = EDVImbrTListLoadImageRGBA(
	    NULL, path,
	    &width, &height, &bpl,
	    FALSE,		/* Do not resize for thumbs list */
	    FALSE,		/* Allow enlarge */
	    window
	);
	if(data_rgba == NULL)
	{
	    /* Failed to load image */
	    EDVImbrSetBusy(imbr, FALSE);
	    return;
	}

	/* Check if the image size is larger in any one dimension than
	 * the ImgView's view widget to determine if we need to zoom
	 * to fit
	 */
	if(w != NULL)
	{
	    if((width > w->allocation.width) ||
               (height > w->allocation.height)
	    )
		need_zoom_to_fit = TRUE;
	}

	/* Create an ImgView image "manually" */
	img = IMGVIEW_IMAGE(g_malloc0(sizeof(imgview_image_struct)));
	img->visual_depth = (vis != NULL) ? vis->depth : -1;
	img->width = width;
	img->height = height;
	img->bpp = 4;
	img->bpl = bpl;
	img->mem = data_rgba;

        /* Update the Thumbs List thumb? */
        if(thumb_num > -1)
        {
	    const gboolean no_enlarge = CFGItemListGetValueI(
                cfg_list, EDV_CFG_PARM_IMBR_THUMB_NO_ENLARGE
            );
	    tlist_struct *tlist = imbr->tlist;
	    if(tlist != NULL)
	    {
                TListSetRGBA(
		    tlist, thumb_num,
		    width, height, bpl,
		    GDK_RGB_DITHER_NORMAL,
		    data_rgba,
		    no_enlarge
		);
		TListSetLoadState(
		    tlist, thumb_num, TLIST_LOAD_STATE_LOADED
		);
	    }
        }

	/* Set the ImgView image to the ImgView */
	if(need_zoom_to_fit)
	    ImgViewSetImageToFit(iv, img);
	else
	    ImgViewSetImage(iv, img);
	img = NULL;	/* Do not reference again after the above call */


	EDVImbrSetBusy(imbr, FALSE);
}
