// 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 *edj = NULL;
static Evas_Object *subsubwin = NULL;
static Evas_Object *subimage = NULL;
static int iw = 0, ih = 0;
static char *grp_first = NULL;

typedef enum
{
   EDJ_NONE,       // does not appear to have groups
   EDJ_THEME,      // what looks like a full theme
   EDJ_BACKGROUND, // a wallpaper background file
   EDJ_ICON,       // an icon edje file
   EDJ_FIRST       // just use the first group found
} Edj_Type;

static void
_thumb_image_setup(void)
{ // create and show image
   subsubwin = elm_win_add(subwin, "inlined2", ELM_WIN_INLINED_IMAGE);
   subimage = elm_win_inlined_image_object_get(subsubwin);
   elm_win_alpha_set(subsubwin, EINA_TRUE);
   evas_object_show(subsubwin);

   edj = edje_object_add(evas_object_evas_get(subsubwin));
   evas_object_show(edj);
}

static void
_thumb_image_file_background_set(const char *file)
{
   edje_object_file_set(edj, file, "e/desktop/background");
   iw = 1920;
   ih = 1080;
}

static void
_thumb_image_file_icon_set(const char *file)
{
   edje_object_file_set(edj, file, "icon");
   edje_object_size_min_get(edj, &iw, &ih);
   if ((iw <= 0) || (ih < 0))
     {
        iw = 256;
        ih = 256;
     }
}

static void
_thumb_image_file_first_group_set(const char *file, const char *grp)
{
   edje_object_file_set(edj, file, grp);
   edje_object_size_min_get(edj, &iw, &ih);
   if (iw <= 0)
     {
        edje_object_size_min_restricted_calc(edj, &iw, &ih, 256, 256);
     }
}

static Eina_Bool
_cb_quit(void *data EINA_UNUSED)
{
   elm_exit();
   return EINA_FALSE;
}

static void
_thumb_image_file_theme_set(const char *file)
{
   const char *s;
   Evas_Object *o, *o_comp, *o_border, *o_win_table, *o_win_bg;
   Evas_Object *o_toolbar, *o_list, *o_frame, *o_box;
   Evas_Object *o_check1, *o_check2, *o_check3, *o_sep;
   Evas_Object *o_radio1, *o_radio2, *o_radio3;
   Evas_Object *o_slider, *o_progress;
   Evas_Object *o_button1, *o_button2;
   Elm_Object_Item *it;

   elm_theme_overlay_add(NULL, file);

   s = elm_theme_group_path_find(NULL, "e/desktop/background");
   edje_object_file_set(edj, s, "e/desktop/background");
   iw = 512;
   ih = 512;

   o = o_comp = edje_object_add(evas_object_evas_get(subsubwin));
   s = elm_theme_group_path_find(NULL, "e/comp/frame/default");
   edje_object_file_set(o, s, "e/comp/frame/default");
   edje_object_signal_emit(o, "e,state,visible", "e");

   o = o_border = edje_object_add(evas_object_evas_get(subsubwin));
   s = elm_theme_group_path_find(NULL, "e/widgets/border/default/border");
   edje_object_file_set(o, s, "e/widgets/border/default/border");
   edje_object_part_text_set(o, "e.text.title", "Title");
   edje_object_signal_emit(o, "e,state,focused", "e");
   evas_object_show(o);
   edje_object_part_swallow(o_comp, "e.swallow.content", o);

   o = o_win_table = elm_table_add(subsubwin);
   edje_object_part_swallow(o_border, "e.swallow.client", o);
   evas_object_show(o);

   o = o_win_bg = elm_bg_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
   elm_table_pack(o_win_table, o, 0, 0, 10, 10);
   evas_object_show(o);

   o = o_toolbar = elm_toolbar_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.0);
   elm_toolbar_homogeneous_set(o, EINA_TRUE);
   elm_toolbar_align_set(o, 0.5);
   elm_table_pack(o_win_table, o, 0, 0, 10, 1);
   evas_object_show(o);

   it = elm_toolbar_item_append(o_toolbar, "folder", "Folder", NULL, NULL);
   elm_toolbar_item_selected_set(it, EINA_TRUE);
   it = elm_toolbar_item_append(o_toolbar, "computer", "Computer", NULL, NULL);
   it = elm_toolbar_item_append(o_toolbar, "audio-volume", "Volume", NULL, NULL);
   it = elm_toolbar_item_append(o_toolbar, "user-available", "User", NULL, NULL);
   it = elm_toolbar_item_append(o_toolbar, "mail-send", "Mail", NULL, NULL);

   o = o_list = elm_list_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
   elm_table_pack(o_win_table, o, 0, 1, 5, 6);
   evas_object_show(o);

   it = elm_list_item_append(o_list, "This", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "List", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "Contains", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "Items", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "Long list item", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "Short item", NULL, NULL, NULL, NULL);
   elm_list_item_selected_set(it, EINA_TRUE);
   it = elm_list_item_append(o_list, "More text here", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "Less text", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "Text", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "Yet more items", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "And even longer items", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "Shorter items", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "Short items", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "Shortest item", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "Second last item", NULL, NULL, NULL, NULL);
   it = elm_list_item_append(o_list, "Last item", NULL, NULL, NULL, NULL);

   elm_list_go(o_list);

   o = o_frame = elm_frame_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
   elm_object_text_set(o, "Frame");
   elm_table_pack(o_win_table, o, 5, 1, 5, 6);
   evas_object_show(o);

   o = o_box = elm_box_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
   elm_box_horizontal_set(o, EINA_FALSE);
   elm_box_align_set(o, 0.5, 0.0);
   elm_object_content_set(o_frame, o);
   evas_object_show(o);

   o = o_check1 = elm_check_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5);
   elm_object_text_set(o, "This option");
   elm_box_pack_end(o_box, o);
   evas_object_show(o);

   o = o_check2 = elm_check_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5);
   elm_object_text_set(o, "Something");
   elm_check_state_set(o, EINA_TRUE);
   elm_box_pack_end(o_box, o);
   evas_object_show(o);

   o = o_check3 = elm_check_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5);
   elm_object_text_set(o, "And another thing");
   elm_check_state_set(o, EINA_TRUE);
   elm_box_pack_end(o_box, o);
   evas_object_show(o);

   o = o_sep = elm_separator_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5);
   elm_separator_horizontal_set(o, EINA_TRUE);
   elm_box_pack_end(o_box, o);
   evas_object_show(o);

   o = o_radio1 = elm_radio_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5);
   elm_radio_state_value_set(o, 1);
   elm_object_text_set(o, "First");
   elm_box_pack_end(o_box, o);
   evas_object_show(o);

   o = o_radio2 = elm_radio_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5);
   elm_radio_state_value_set(o, 2);
   elm_radio_group_add(o, o_radio1);
   elm_object_text_set(o, "Second");
   elm_box_pack_end(o_box, o);
   evas_object_show(o);

   o = o_radio3 = elm_radio_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5);
   elm_radio_state_value_set(o, 3);
   elm_radio_group_add(o, o_radio1);
   elm_object_text_set(o, "Third");
   elm_box_pack_end(o_box, o);
   evas_object_show(o);

   elm_radio_value_set(o_radio1, 2);

   o = o_slider = elm_slider_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 1.0);
   elm_object_text_set(o, "Slider");
   elm_slider_unit_format_set(o, "%1.1f");
   elm_slider_min_max_set(o, 0, 10);
   elm_slider_value_set(o, 3.7);
   elm_table_pack(o_win_table, o, 0, 7, 10, 1);
   evas_object_show(o);

   o = o_progress = elm_progressbar_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 1.0);
   elm_object_text_set(o, "Progress");
   elm_progressbar_value_set(o, 0.7);
   elm_progressbar_unit_format_set(o, "%1.1f");
   elm_table_pack(o_win_table, o, 0, 8, 10, 1);
   evas_object_show(o);

   o = o_button1 = elm_button_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 1.0);
   elm_object_text_set(o, "Select");
   elm_table_pack(o_win_table, o, 0, 9, 5, 1);
   evas_object_show(o);

   o = o_button2 = elm_button_add(o_win_table);
   evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
   evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 1.0);
   elm_object_text_set(o, "Cancel");
   elm_table_pack(o_win_table, o, 5, 9, 5, 1);
   evas_object_show(o);

   o = o_comp;
   evas_object_move(o, 64, 64);
   evas_object_resize(o, 384, 384);
   evas_object_show(o);

   ecore_timer_add(1.0, _cb_quit, NULL);
   elm_run();
}

static Edj_Type
_thumb_edje_type_guess(const char *file)
{
   Eina_List *l;
   const char *s;
   Eina_List *groups = edje_file_collection_list(file);
   if (!groups) return EDJ_NONE;
   Eina_Bool have_icon = EINA_FALSE;
   Eina_Bool have_e_background = EINA_FALSE;
   Eina_Bool have_e_border = EINA_FALSE;
   Eina_Bool have_elm_button = EINA_FALSE;
   Eina_Bool have_elm_check = EINA_FALSE;
   Eina_Bool have_elm_genlist = EINA_FALSE;
   Eina_Bool have_elm_frame = EINA_FALSE;

   EINA_LIST_FOREACH(groups, l, s)
     {
        if (!grp_first) grp_first = strdup(s);
#define MATCH(__str, __val) (!strcmp(s, __str)) have_ ## __val = EINA_TRUE
        if      MATCH("icon", icon);
        else if MATCH("e/desktop/background", e_background);
        else if MATCH("e/widgets/border/default/border", e_border);
        else if MATCH("elm/button/base/default", elm_button);
        else if MATCH("elm/check/base/default", elm_check);
        else if MATCH("elm/genlist/item/default/default", elm_genlist);
        else if MATCH("elm/frame/base/default", elm_frame);
     }
   edje_file_collection_list_free(groups);

   if (have_e_background && have_e_border && have_elm_button &&
       have_elm_check && have_elm_genlist && have_elm_frame)
     return EDJ_THEME;
   else if (have_e_background)
     return EDJ_BACKGROUND;
   else if (have_icon)
     return EDJ_ICON;
   return EDJ_FIRST;
}

int
thumb_edje(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];
   Edj_Type etype = _thumb_edje_type_guess(path);

   if      (etype == EDJ_NONE) return 2;

   elm_config_scale_set(1.0);
   _thumb_image_setup();

   if (etype == EDJ_BACKGROUND)
     { // add filled background
        _thumb_image_file_background_set(path);
     }
   else if (etype == EDJ_ICON)
     { // an edj icon file
        _thumb_image_file_icon_set(path);
     }
   else if (etype == EDJ_THEME)
     { // it's a theme - let's fake up some gui setup
        _thumb_image_file_theme_set(path);
     }
   else if (etype == EDJ_FIRST)
     { // just load first group we find
        _thumb_image_file_first_group_set(path, grp_first);
     }
   // 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(edj, iw, ih);
   evas_object_resize(subsubwin, iw, ih);

   // preview
   evas_object_resize(subimage, w, h);
   evas_object_resize(subwin, w, h);
   // render our current state and pick up pixel results
   elm_win_render(subsubwin);
   elm_win_render(subwin);
   // save out preview size
   snprintf(buf, sizeof(buf), "image/preview");
   thumb_image_write(ef, buf, image, EINA_TRUE, 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(subimage, 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, EINA_TRUE, EINA_TRUE);
     }

   return 0;
}
