// generate thumbnail for images
#include "thumb.h"

// XXX: can do progressive resize down ie scale to 512 then take 512 and
// halve to 256 then halve it to 128 etc. rather than render from orig to
// target size....

static Evas_Object *im = NULL;
static Eina_Bool alpha = EINA_FALSE;
static int iw = 0, ih = 0;

static void
_thumb_image_setup(void)
{ // create and show image
   im = evas_object_image_filled_add(evas_object_evas_get(subwin));
   evas_object_show(im);
}

static void
_thumb_image_file_set(const char *file)
{ // set file to image, get size & alpha
   evas_object_image_file_set(im, file, NULL);
   evas_object_image_size_get(im, &iw, &ih);
   alpha = evas_object_image_alpha_get(im);
}

static void
_thumb_image_hsv_sort_render(unsigned int *dst, int w, int h)
{ // render image down to a specific size (small) and copy to dest
   void *pixels;

   evas_object_resize(im, w, h);
   evas_object_resize(subwin, w, h);
   elm_win_render(subwin);
   pixels = evas_object_image_data_get(image, EINA_FALSE);
   if (!pixels) return;
   memcpy(dst, pixels, w * h * sizeof(int));
   evas_object_image_data_set(image, pixels);
}

static void
_thumb_image_hsv_sort_key_write(Eet_File *ef, const char *key)
{ // get rendered pixels from image representing subwin and write out AHVS key
   unsigned int *data4x4, *data2x2, *data1x1;
   unsigned char id2[256];
   int n, i, hi, si, vi;
   float h, s, v;
   const int pat2x2[4]  = {  0,  3,  1,  2 };
   const int pat4x4[16] = {  5, 10,  6,  9,
                             0, 15,  3, 12,
                             1, 14,  7,  8,
                             4, 11,  2, 13 };

   data4x4 = malloc(4 * 4 * sizeof(int));
   data2x2 = malloc(2 * 2 * sizeof(int));
   data1x1 = malloc(1 * 1 * sizeof(int));

   if ((!data4x4) || (!data2x2) || (!data1x1)) goto err;

   _thumb_image_hsv_sort_render(data4x4, 4, 4);
   _thumb_image_hsv_sort_render(data2x2, 2, 2);
   _thumb_image_hsv_sort_render(data1x1, 1, 1);

   n = 0;

#define A(v) (((v) >> 24) & 0xff)
#define R(v) (((v) >> 16) & 0xff)
#define G(v) (((v) >> 8 ) & 0xff)
#define B(v) (((v)      ) & 0xff)
#define HSV(p) do {                                     \
   evas_color_rgb_to_hsv(R(p), G(p), B(p), &h, &s, &v); \
   hi = 20 * (h / 360.0);                               \
   si = 20 * s;                                         \
   vi = 20 * v;                                         \
   if (si < 2) hi = 25;                                 \
} while (0)
#define SAVEX(x) id2[n++] = 'a' + (x)

   SAVEX(A(data1x1[0]));
   for (i = 0; i < 4 ; i++) SAVEX(A(data2x2[pat2x2[i]]));
   for (i = 0; i < 16; i++) SAVEX(A(data4x4[pat4x4[i]]));

#define STORE(val) \
   HSV(data1x1[0]); \
   SAVEX(val); \
   for (i = 0; i < 4; i++) { \
      HSV(data2x2[pat2x2[i]]); \
      SAVEX(val); \
   } \
   for (i = 0; i < 16; i++) { \
      HSV(data4x4[pat4x4[i]]); \
      SAVEX(val); \
   }

   STORE(hi);
   STORE(vi);
   STORE(si);

   id2[n++] = 0;

   eet_write(ef, key, id2, n,
             EET_COMPRESSION_NONE);
err:
   free(data4x4);
   free(data2x2);
   free(data1x1);
}

int
thumb_image(Eet_File *ef, const char *path, const char *mime EINA_UNUSED, const char *thumb EINA_UNUSED)
{
   const int sizes[] = { 512, 256, 128, 64, 32, 16, 0 };
   int w, h, i;
   char buf[128];
   unsigned char a;

   _thumb_image_setup();
   // add filled image to then size accordingly
   _thumb_image_file_set(path);
   // if size is bunk - we can't load it...
   if ((iw <= 0) || (ih < 0)) return 2;

   // write a big 1024x1024 preview (but no larger than the original image)
   w = iw; h = ih; scale(&w, &h, 1024, 1024, EINA_TRUE);

   // resize to target size
   evas_object_resize(im, w, h);
   evas_object_resize(subwin, w, h);
   // render our current state and pick up pixel results
   elm_win_render(subwin);
   // save out preview size
   snprintf(buf, sizeof(buf), "image/preview");
   thumb_image_write(ef, buf, image, alpha, EINA_TRUE);
   snprintf(buf, sizeof(buf), "%i %i", w, h);
   eet_write(ef, "image/preview/size", buf, strlen(buf) + 1,
             EET_COMPRESSION_NONE);

   // multiple thumb sizes so can load/pick the best one at runtime
   for (i = 0; sizes[i] != 0; i++)
     {
        // scale down and keep aspect
        w = iw; h = ih; scale(&w, &h, sizes[i], sizes[i], EINA_FALSE);
        // resize to target size
        evas_object_resize(im, w, h);
        evas_object_resize(subwin, w, h);
        // render our current state and pick up pixel results
        elm_win_render(subwin);
        // save out thumb size
        snprintf(buf, sizeof(buf), "image/thumb/%i", sizes[i]);
        thumb_image_write(ef, buf, image, alpha, EINA_TRUE);
     }

   _thumb_image_hsv_sort_key_write(ef, "image/sort_key");

   // write original alpha flag
   a = alpha;
   if (alpha)
     eet_write(ef, "orig/image/alpha", &a, 1,
               EET_COMPRESSION_NONE);
   // write original size
   snprintf(buf, sizeof(buf), "%i %i", iw, ih);
   eet_write(ef, "orig/image/size", buf, strlen(buf) + 1,
             EET_COMPRESSION_NONE);
   return 0;
}
