#include "ephoto.h"

typedef enum _Ephoto_Slideshow_Move Ephoto_Slideshow_Move;
typedef struct _Ephoto_Slideshow    Ephoto_Slideshow;

enum _Ephoto_Slideshow_Move
{
   EPHOTO_SLIDESHOW_MOVE_LEFT_TO_RIGHT,
   EPHOTO_SLIDESHOW_MOVE_RIGHT_TO_LEFT,
   EPHOTO_SLIDESHOW_MOVE_TOP_TO_BOTTOM,
   EPHOTO_SLIDESHOW_MOVE_BOTTOM_TO_TOP,
   EPHOTO_SLIDESHOW_MOVE_LEFT_IN,
   EPHOTO_SLIDESHOW_MOVE_RIGHT_IN,
   EPHOTO_SLIDESHOW_MOVE_TOP_IN,
   EPHOTO_SLIDESHOW_MOVE_BOTTOM_IN,
   EPHOTO_SLIDESHOW_MOVE_LEFT_OUT,
   EPHOTO_SLIDESHOW_MOVE_RIGHT_OUT,
   EPHOTO_SLIDESHOW_MOVE_TOP_OUT,
   EPHOTO_SLIDESHOW_MOVE_BOTTOM_OUT,
   EPHOTO_SLIDESHOW_MOVE_LEFT_TOP_CORNER,
   EPHOTO_SLIDESHOW_MOVE_RIGHT_TOP_CORNER,
   EPHOTO_SLIDESHOW_MOVE_RIGHT_BOTTOM_CORNER,
   EPHOTO_SLIDESHOW_MOVE_LEFT_BOTTOM_CORNER,
   EPHOTO_SLIDESHOW_MOVE_LEFT_TOP_CORNER_IN,
   EPHOTO_SLIDESHOW_MOVE_RIGHT_TOP_CORNER_IN,
   EPHOTO_SLIDESHOW_MOVE_RIGHT_BOTTOM_CORNER_IN,
   EPHOTO_SLIDESHOW_MOVE_LEFT_BOTTOM_CORNER_IN,
   EPHOTO_SLIDESHOW_MOVE_LEFT_TOP_CORNER_OUT,
   EPHOTO_SLIDESHOW_MOVE_RIGHT_TOP_CORNER_OUT,
   EPHOTO_SLIDESHOW_MOVE_RIGHT_BOTTOM_CORNER_OUT,
   EPHOTO_SLIDESHOW_MOVE_LEFT_BOTTOM_CORNER_OUT
};

struct _Ephoto_Slideshow
{
   Ephoto               *ephoto;
   Evas_Object          *current_item;
   Evas_Object          *old_item;
   Evas_Object          *slideshow;
   Evas_Object          *event;
   Evas_Object          *notify;
   Evas_Object          *notify_box;
   Eina_List            *entries;
   Evas_Object          *pause;
   Evas_Object          *pause_after;
   Evas_Object          *fullscreen;
   Evas_Object          *fullscreen_after;
   Evas_Object          *exit;
   Ephoto_Entry         *entry;
   Eina_Bool             playing;
   Eina_Bool             timer_end;
   Ecore_Timer          *timer;
   Ephoto_Slideshow_Move move;
   float                 timeout;
   int                   current;
};

static Evas_Object *_slideshow_item_get(Ephoto_Slideshow *ss,
                                        Ephoto_Entry *entry, Evas_Object *parent);
static Eina_Bool    _slideshow_transition(void *data);
static void         _slideshow_play(Ephoto_Slideshow *ss);
static void         _slideshow_pause(Ephoto_Slideshow *ss);
static Evas_Object *_add_icon(Evas_Object *parent, const char *icon,
                              const char *label, Evas_Object *before);

static void
_image_shown(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
             void *event_data EINA_UNUSED)
{
   Ephoto_Entry *entry = data;

   ephoto_title_set(entry->ephoto, entry->basename);
}

static const char *
_slideshow_move_end_get(Ephoto_Slideshow *ss)
{
   switch (ss->move)
     {
      case EPHOTO_SLIDESHOW_MOVE_LEFT_TO_RIGHT:
        return "ephoto,slideshow,move,left,to,right";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_TO_LEFT:
        return "ephoto,slideshow,move,right,to,left";

      case EPHOTO_SLIDESHOW_MOVE_TOP_TO_BOTTOM:
        return "ephoto,slideshow,move,top,to,bottom";

      case EPHOTO_SLIDESHOW_MOVE_BOTTOM_TO_TOP:
        return "ephoto,slideshow,move,bottom,to,top";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_IN:
        return "ephoto,slideshow,move,left,in";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_IN:
        return "ephoto,slideshow,move,right,in";

      case EPHOTO_SLIDESHOW_MOVE_TOP_IN:
        return "ephoto,slideshow,move,top,in";

      case EPHOTO_SLIDESHOW_MOVE_BOTTOM_IN:
        return "ephoto,slideshow,move,bottom,in";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_OUT:
        return "ephoto,slideshow,move,left,out";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_OUT:
        return "ephoto,slideshow,move,right,out";

      case EPHOTO_SLIDESHOW_MOVE_TOP_OUT:
        return "ephoto,slideshow,move,top,out";

      case EPHOTO_SLIDESHOW_MOVE_BOTTOM_OUT:
        return "ephoto,slideshow,move,bottom,out";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_TOP_CORNER:
        return "ephoto,slideshow,move,left,top,corner";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_TOP_CORNER:
        return "ephoto,slideshow,move,right,top,corner";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_BOTTOM_CORNER:
        return "ephoto,slideshow,move,right,bottom,corner";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_BOTTOM_CORNER:
        return "ephoto,slideshow,move,left,bottom,corner";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_TOP_CORNER_IN:
        return "ephoto,slideshow,move,left,top,corner,in";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_TOP_CORNER_IN:
        return "ephoto,slideshow,move,right,top,corner,in";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_BOTTOM_CORNER_IN:
        return "ephoto,slideshow,move,right,bottom,corner,in";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_BOTTOM_CORNER_IN:
        return "ephoto,slideshow,move,left,bottom,corner,in";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_TOP_CORNER_OUT:
        return "ephoto,slideshow,move,left,top,corner,out";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_TOP_CORNER_OUT:
        return "ephoto,slideshow,move,right,top,corner,out";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_BOTTOM_CORNER_OUT:
        return "ephoto,slideshow,move,right,bottom,corner,out";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_BOTTOM_CORNER_OUT:
        return "ephoto,slideshow,move,left,bottom,corner,out";

      default: return "default";
     }
}

static const char *
_slideshow_move_start_get(Ephoto_Slideshow *ss)
{
   switch (ss->move)
     {
      case EPHOTO_SLIDESHOW_MOVE_LEFT_TO_RIGHT:
        return "ephoto,slideshow,default,left,to,right";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_TO_LEFT:
        return "ephoto,slideshow,default,right,to,left";

      case EPHOTO_SLIDESHOW_MOVE_TOP_TO_BOTTOM:
        return "ephoto,slideshow,default,top,to,bottom";

      case EPHOTO_SLIDESHOW_MOVE_BOTTOM_TO_TOP:
        return "ephoto,slideshow,default,bottom,to,top";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_IN:
        return "ephoto,slideshow,default,left,in";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_IN:
        return "ephoto,slideshow,default,right,in";

      case EPHOTO_SLIDESHOW_MOVE_TOP_IN:
        return "ephoto,slideshow,default,top,in";

      case EPHOTO_SLIDESHOW_MOVE_BOTTOM_IN:
        return "ephoto,slideshow,default,bottom,in";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_OUT:
        return "ephoto,slideshow,default,left,out";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_OUT:
        return "ephoto,slideshow,default,right,out";

      case EPHOTO_SLIDESHOW_MOVE_TOP_OUT:
        return "ephoto,slideshow,default,top,out";

      case EPHOTO_SLIDESHOW_MOVE_BOTTOM_OUT:
        return "ephoto,slideshow,default,bottom,out";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_TOP_CORNER:
        return "ephoto,slideshow,default,left,top,corner";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_TOP_CORNER:
        return "ephoto,slideshow,default,right,top,corner";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_BOTTOM_CORNER:
        return "ephoto,slideshow,default,right,bottom,corner";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_BOTTOM_CORNER:
        return "ephoto,slideshow,default,left,bottom,corner";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_TOP_CORNER_IN:
        return "ephoto,slideshow,default,left,top,corner,in";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_TOP_CORNER_IN:
        return "ephoto,slideshow,default,right,top,corner,in";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_BOTTOM_CORNER_IN:
        return "ephoto,slideshow,default,right,bottom,corner,in";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_BOTTOM_CORNER_IN:
        return "ephoto,slideshow,default,left,bottom,corner,in";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_TOP_CORNER_OUT:
        return "ephoto,slideshow,default,left,top,corner,out";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_TOP_CORNER_OUT:
        return "ephoto,slideshow,default,right,top,corner,out";

      case EPHOTO_SLIDESHOW_MOVE_RIGHT_BOTTOM_CORNER_OUT:
        return "ephoto,slideshow,default,right,bottom,corner,out";

      case EPHOTO_SLIDESHOW_MOVE_LEFT_BOTTOM_CORNER_OUT:
        return "ephoto,slideshow,default,left,bottom,corner,out";

      default: return "default";
     }
}

static void
_slideshow_move_randomize(Ephoto_Slideshow *ss)
{
   int i, r = 0;
   int range = 24;
   int buckets = RAND_MAX / range;
   int limit = buckets * range;

   r = rand();
   while (r >= limit)
     {
        r = rand();
     }
   i = r / buckets;

   switch (i)
     {
      case 0:
        ss->move = EPHOTO_SLIDESHOW_MOVE_LEFT_TO_RIGHT;
        break;

      case 1:
        ss->move = EPHOTO_SLIDESHOW_MOVE_RIGHT_TO_LEFT;
        break;

      case 2:
        ss->move = EPHOTO_SLIDESHOW_MOVE_TOP_TO_BOTTOM;
        break;

      case 3:
        ss->move = EPHOTO_SLIDESHOW_MOVE_BOTTOM_TO_TOP;
        break;

      case 4:
        ss->move = EPHOTO_SLIDESHOW_MOVE_LEFT_IN;
        break;

      case 5:
        ss->move = EPHOTO_SLIDESHOW_MOVE_RIGHT_IN;
        break;

      case 6:
        ss->move = EPHOTO_SLIDESHOW_MOVE_TOP_IN;
        break;

      case 7:
        ss->move = EPHOTO_SLIDESHOW_MOVE_BOTTOM_IN;
        break;

      case 8:
        ss->move = EPHOTO_SLIDESHOW_MOVE_LEFT_OUT;
        break;

      case 9:
        ss->move = EPHOTO_SLIDESHOW_MOVE_RIGHT_OUT;
        break;

      case 10:
        ss->move = EPHOTO_SLIDESHOW_MOVE_TOP_OUT;
        break;

      case 11:
        ss->move = EPHOTO_SLIDESHOW_MOVE_BOTTOM_OUT;
        break;

      case 12:
        ss->move = EPHOTO_SLIDESHOW_MOVE_LEFT_TOP_CORNER;
        break;

      case 13:
        ss->move = EPHOTO_SLIDESHOW_MOVE_RIGHT_TOP_CORNER;
        break;

      case 14:
        ss->move = EPHOTO_SLIDESHOW_MOVE_RIGHT_BOTTOM_CORNER;
        break;

      case 15:
        ss->move = EPHOTO_SLIDESHOW_MOVE_LEFT_BOTTOM_CORNER;
        break;

      case 16:
        ss->move = EPHOTO_SLIDESHOW_MOVE_LEFT_TOP_CORNER_IN;
        break;

      case 17:
        ss->move = EPHOTO_SLIDESHOW_MOVE_RIGHT_TOP_CORNER_IN;
        break;

      case 18:
        ss->move = EPHOTO_SLIDESHOW_MOVE_RIGHT_BOTTOM_CORNER_IN;
        break;

      case 19:
        ss->move = EPHOTO_SLIDESHOW_MOVE_LEFT_BOTTOM_CORNER_IN;
        break;

      case 20:
        ss->move = EPHOTO_SLIDESHOW_MOVE_LEFT_TOP_CORNER_OUT;
        break;

      case 21:
        ss->move = EPHOTO_SLIDESHOW_MOVE_RIGHT_TOP_CORNER_OUT;
        break;

      case 22:
        ss->move = EPHOTO_SLIDESHOW_MOVE_RIGHT_BOTTOM_CORNER_OUT;
        break;

      case 23:
        ss->move = EPHOTO_SLIDESHOW_MOVE_LEFT_BOTTOM_CORNER_OUT;
        break;

      default: ss->move = EPHOTO_SLIDESHOW_MOVE_LEFT_TO_RIGHT;
     }
}

static void
_on_transition_raise(void *data, Evas_Object *obj EINA_UNUSED,
                     const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   evas_object_raise(ss->current_item);
}

static void
_on_transition_end(void *data, Evas_Object *obj EINA_UNUSED,
                   const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   if (ss->old_item)
     {
        elm_layout_content_unset(ss->slideshow, "ephoto.swallow.slideshow.item");
        evas_object_del(ss->old_item);
        ss->old_item = NULL;
     }
   if (ss->current_item)
     {
        elm_layout_content_unset(ss->slideshow, "ephoto.swallow.slideshow.item2");
     }
   elm_layout_content_set(ss->slideshow, "ephoto.swallow.slideshow.item",
                          ss->current_item);
   evas_object_raise(ss->current_item);
   evas_object_show(ss->current_item);
   elm_layout_signal_emit(ss->slideshow, "ephoto,transition,done", "ephoto");

   if (!ss->ephoto->gadget)
     ss->timeout = ss->ephoto->config->slideshow_timeout;
   else
     ss->timeout = ss->ephoto->gadget_config->slideshow_timeout;
   if (ss->timer)
     ecore_timer_del(ss->timer);
   ss->timer = NULL;
   if (ss->playing)
     ss->timer = ecore_timer_loop_add(ss->timeout, _slideshow_transition, ss);
}

static Evas_Object *
_slideshow_item_get(Ephoto_Slideshow *ss, Ephoto_Entry *entry, Evas_Object *parent)
{
   const char *group = NULL;
   const char *ext = strrchr(entry->path, '.');
   Evas_Coord w, h, sw, sh;
   Evas_Object *layout, *image;
   Edje_Message_Float_Set *msg;

   if (ext)
     {
        ext++;
        if ((strcasecmp(ext, "edj") == 0))
          {
             if (edje_file_group_exists(entry->path, "e/desktop/background"))
               group = "e/desktop/background";
             else
               {
                  Eina_List *g = edje_file_collection_list(entry->path);

                  group = eina_list_data_get(g);
                  edje_file_collection_list_free(g);
               }
          }
     }
   layout = elm_layout_add(parent);
   elm_layout_file_set(layout, PACKAGE_DATA_DIR "/themes/ephoto.edj",
                       "ephoto,slideshow,item");
   if (ss->ephoto->gadget)
     elm_layout_signal_emit(layout, "gadget", "ephoto");
   EPHOTO_EXPAND(layout);
   EPHOTO_FILL(layout);
   evas_object_data_set(layout, "entry", entry);

   image = elm_image_add(parent);
   if (ss->ephoto->config->movess && !ss->ephoto->gadget)
     {
        elm_image_preload_disabled_set(image, EINA_FALSE);
        elm_image_smooth_set(image, EINA_FALSE);
        elm_image_fill_outside_set(image, EINA_TRUE);
     }
   else if (!ss->ephoto->config->movess || ss->ephoto->gadget)
     {
        evas_object_image_load_orientation_set(image, EINA_TRUE);
        evas_object_image_filled_set(image, EINA_TRUE);   
        evas_object_image_preload(image, EINA_FALSE);
     }
   elm_image_file_set(image, entry->path, group);
   EPHOTO_EXPAND(image);
   EPHOTO_FILL(image);
   evas_object_event_callback_add(image, EVAS_CALLBACK_SHOW, _image_shown,
                                  entry);
   evas_object_image_size_get(elm_image_object_get(image), &w, &h);
   evas_object_geometry_get(parent, 0, 0, &sw, &sh);
   if (w < sw && h < sh)
     {
        evas_object_size_hint_max_set(image, w, h);
        elm_image_fill_outside_set(image, EINA_FALSE);
     }
   elm_layout_content_set(layout, "ephoto.swallow.slideshow.item", image);

   msg = alloca(sizeof(Edje_Message_Float_Set) + (1 * sizeof(float)));
   msg->count = 1;
   msg->val[0] = (float)ss->timeout;
   edje_object_message_send(elm_layout_edje_get(layout),
                            EDJE_MESSAGE_FLOAT_SET, 1, msg);

   return layout;
}

static Eina_Bool
_slideshow_transition(void *data)
{
   Ephoto_Slideshow *ss = data;
   char buf[PATH_MAX];

   if (ss->timer_end)
     ss->current += 1;
   else
     ss->timer_end = EINA_TRUE;
   if (!eina_list_nth(ss->entries, ss->current))
     ss->current = 0;
   if (ss->old_item)
     evas_object_del(ss->old_item);

   ss->old_item = ss->current_item;
   ss->current_item = _slideshow_item_get(ss, eina_list_nth(ss->entries, ss->current),
                                          ss->slideshow);
   elm_layout_content_set(ss->slideshow, "ephoto.swallow.slideshow.item2",
                          ss->current_item);
   evas_object_show(ss->current_item);

   snprintf(buf, PATH_MAX, "ephoto,%s", ss->ephoto->config->slideshow_transition);
   elm_layout_signal_emit(ss->slideshow, buf, "ephoto");
   if (!ss->ephoto->gadget)
     {
        if (ss->ephoto->config->movess)
          {
             elm_layout_signal_emit(ss->current_item, _slideshow_move_start_get(ss), "ephoto");
             elm_layout_signal_emit(ss->current_item, _slideshow_move_end_get(ss), "ephoto");
             _slideshow_move_randomize(ss);
          }
     }
   if (ss->timer)
     ecore_timer_del(ss->timer);
   ss->timer = NULL;

   return EINA_FALSE;
}

static void
_slideshow_play(Ephoto_Slideshow *ss)
{
   Edje_Message_Float_Set *msg;

   if (!ss->current_item)
     {
        if (!eina_list_nth(ss->entries, ss->current))
          ss->current = 0;
        ss->current_item = _slideshow_item_get(ss, eina_list_nth(ss->entries, ss->current),
                                               ss->slideshow);
        elm_layout_content_set(ss->slideshow, "ephoto.swallow.slideshow.item",
                               ss->current_item);
        evas_object_raise(ss->current_item);
        evas_object_show(ss->current_item);
     }
   if (!ss->ephoto->gadget)
     {
        if (ss->ephoto->config->movess)
          _slideshow_move_randomize(ss);
     }
   msg = alloca(sizeof(Edje_Message_Float_Set) + (1 * sizeof(float)));
   msg->count = 1;
   msg->val[0] = (float)ss->timeout;
   edje_object_message_send(elm_layout_edje_get(ss->current_item),
                            EDJE_MESSAGE_FLOAT_SET, 1, msg);

   if (!ss->ephoto->gadget)
     {
        if (ss->ephoto->config->movess)
          {
             elm_layout_signal_emit(ss->current_item, _slideshow_move_start_get(ss), "ephoto");
             elm_layout_signal_emit(ss->current_item, _slideshow_move_end_get(ss), "ephoto");
             _slideshow_move_randomize(ss);
          }
     }

   if (ss->timer)
     ecore_timer_del(ss->timer);
   ss->timer = ecore_timer_loop_add(ss->timeout, _slideshow_transition, ss);
}

static void
_slideshow_pause(Ephoto_Slideshow *ss)
{
   if (ss->timer)
     ss->timer = ecore_timer_del(ss->timer);
   ss->timer = NULL;
}

static void
_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
            void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;
   Ephoto_Entry *entry;

   if (elm_win_fullscreen_get(ss->ephoto->win))
     {
        elm_box_pack_end(ss->ephoto->statusbar, ss->ephoto->exit);
        evas_object_show(ss->ephoto->exit);
     }
   else
     {
        elm_box_unpack(ss->ephoto->statusbar, ss->ephoto->exit);
        evas_object_hide(ss->ephoto->exit);
     }
   if (ss->current_item)
     entry = evas_object_data_get(ss->current_item, "entry");
   else
     entry = ss->entry;
   if (ss->event)
     {
        evas_object_del(ss->event);
        ss->event = NULL;
     }
   evas_object_del(ss->notify_box);
   evas_object_del(ss->notify);
   ss->notify_box = NULL;
   ss->notify = NULL;
   if (!ss->ephoto->gadget)
     evas_object_smart_callback_call(ss->slideshow, "back", entry);
   if (ss->old_item)
     {
        elm_layout_content_unset(ss->slideshow, "ephoto.swallow.slideshow.item2");
        evas_object_del(ss->old_item);
     }
   if (ss->current_item)
     {
        elm_layout_content_unset(ss->slideshow, "ephoto.swallow.slideshow.item");
        evas_object_del(ss->current_item);
     }
   ss->old_item = NULL;
   ss->current_item = NULL;
   if (ss->timer)
     ecore_timer_del(ss->timer);
   ss->timer = NULL;
   ss->current = 0;
   ss->playing = 0;
}

static void
_entry_free(void *data, const Ephoto_Entry *entry EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   ss->entry = NULL;
}

static void
_slideshow_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
               void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   if (ss->entry)
     ephoto_entry_free_listener_del(ss->entry, _entry_free, ss);
   free(ss);
}

static void
_back(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;
   Ephoto_Entry *entry;

   if (elm_win_fullscreen_get(ss->ephoto->win))
     {
        elm_box_pack_end(ss->ephoto->statusbar, ss->ephoto->exit);
        evas_object_show(ss->ephoto->exit);
     }
   else
     {
        elm_box_unpack(ss->ephoto->statusbar, ss->ephoto->exit);
        evas_object_hide(ss->ephoto->exit);
     }
   if (ss->current_item)
     entry = evas_object_data_get(ss->current_item, "entry");
   else
     entry = ss->entry;
   if (ss->event)
     {
        evas_object_del(ss->event);
        ss->event = NULL;
     }
   evas_object_del(ss->notify_box);
   evas_object_del(ss->notify);
   ss->notify_box = NULL;
   ss->notify = NULL;
   evas_object_smart_callback_call(ss->slideshow, "back", entry);
   if (ss->old_item)
     {
        elm_layout_content_unset(ss->slideshow, "ephoto.swallow.slideshow.item2");
        evas_object_del(ss->old_item);
     }
   if (ss->current_item)
     {
        elm_layout_content_unset(ss->slideshow, "ephoto.swallow.slideshow.item");
        evas_object_del(ss->current_item);
     }
   ss->old_item = NULL;
   ss->current_item = NULL;
   if (ss->timer)
     ecore_timer_del(ss->timer);
   ss->timer = NULL;
   ss->current = 0;
   ss->playing = 0;
}

static void
_first(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   if (ss->timer)
     {
        ecore_timer_del(ss->timer);
        ss->timer = NULL;
     }
   ss->current = 0;
   ss->timer_end = EINA_FALSE;
   _slideshow_transition(ss);
}

static void
_next(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   if (ss->timer)
     {
        ecore_timer_del(ss->timer);
        ss->timer = NULL;
     }
   ss->current += 1;
   ss->timer_end = EINA_FALSE;
   _slideshow_transition(ss);
}

static void
_pause(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   evas_object_del(ss->pause);

   if (ss->playing)
     {
        _slideshow_pause(ss);
        ss->pause =
          _add_icon(ss->notify_box, "media-playback-start", _("Play"),
                    ss->pause_after);
        evas_object_smart_callback_add(ss->pause, "clicked", _pause, ss);
        ss->playing = 0;
     }
   else
     {
        _slideshow_play(ss);
        ss->pause =
          _add_icon(ss->notify_box, "media-playback-pause", _("Pause"),
                    ss->pause_after);
        evas_object_smart_callback_add(ss->pause, "clicked", _pause, ss);
        ss->playing = 1;
     }
}

static void
_previous(void *data, Evas_Object *obj EINA_UNUSED,
          void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   if (ss->timer)
     {
        ecore_timer_del(ss->timer);
        ss->timer = NULL;
     }
   ss->current -= 1;
   ss->timer_end = EINA_FALSE;
   _slideshow_transition(ss);
}

static void
_last(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   if (ss->timer)
     {
        ecore_timer_del(ss->timer);
        ss->timer = NULL;
     }
   ss->current = eina_list_count(ss->entries) - 1;
   ss->timer_end = EINA_FALSE;
   _slideshow_transition(ss);
}

static void
_fullscreen(void *data, Evas_Object *obj EINA_UNUSED,
            void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   evas_object_del(ss->fullscreen);

   if (elm_win_fullscreen_get(ss->ephoto->win))
     {
        ss->fullscreen =
          _add_icon(ss->notify_box, "view-fullscreen", _("Fullscreen"),
                    ss->fullscreen_after);
        evas_object_smart_callback_add(ss->fullscreen, "clicked",
                                       _fullscreen, ss);
        elm_win_fullscreen_set(ss->ephoto->win, EINA_FALSE);
        elm_box_unpack(ss->notify_box, ss->exit);
        evas_object_hide(ss->exit);
     }
   else
     {
        ss->fullscreen =
          _add_icon(ss->notify_box, "view-restore", _("Normal"),
                    ss->fullscreen_after);
        evas_object_smart_callback_add(ss->fullscreen, "clicked",
                                       _fullscreen, ss);
        elm_win_fullscreen_set(ss->ephoto->win, EINA_TRUE);
        elm_box_pack_end(ss->notify_box, ss->exit);
        evas_object_show(ss->exit);
     }
}

static void
_settings(void *data, Evas_Object *obj EINA_UNUSED,
          void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   ephoto_config_main(ss->ephoto);
}

static void
_gadget_settings_save(void *data, Evas_Object *obj EINA_UNUSED,
          void *event_info EINA_UNUSED)
{
   Evas_Object *popup = data, *fentry, *spinner;
   Ephoto_Slideshow *ss = evas_object_data_get(popup, "slideshow");
   const char *path;

   fentry = evas_object_data_get(popup, "fentry");
   spinner = evas_object_data_get(popup, "timeout");

   ss->ephoto->gadget_config->slideshow_timeout = elm_spinner_value_get(spinner);
   path = elm_fileselector_path_get(fentry);
   eina_stringshare_replace(&ss->ephoto->gadget_config->directory, path);
   if (ecore_file_is_dir(path))
     ephoto_directory_set(ss->ephoto, path, NULL, EINA_FALSE, EINA_TRUE);

   ephoto_gadget_config_save(ss->ephoto);
   evas_object_del(popup);
}

static void
_popup_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_data EINA_UNUSED)
{
   evas_object_del(obj);
}

static void
_gadget_settings(void *data, Evas_Object *obj EINA_UNUSED,
          void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;
   Evas_Object *popup, *but, *table, *fentry, *label, *spinner, *rect;
   char buf[PATH_MAX];

   popup = elm_win_add(ss->ephoto->win, "win", ELM_WIN_BASIC);
   if (ss->ephoto->gadget)
     elm_win_alpha_set(popup, 1);
   else
     elm_win_autodel_set(popup, 1);
   evas_object_data_set(popup, "slideshow", ss);
   evas_object_event_callback_add(popup, EVAS_CALLBACK_HIDE, _popup_del, NULL);

   table = elm_table_add(popup);
   elm_table_homogeneous_set(table, EINA_FALSE);
   EPHOTO_EXPAND(table);
   EPHOTO_FILL(table);
   elm_win_resize_object_add(popup, table);
   evas_object_show(table);

   fentry = elm_fileselector_add(table);
   elm_fileselector_is_save_set(fentry, EINA_FALSE);
   elm_fileselector_expandable_set(fentry, EINA_FALSE);
   elm_fileselector_path_set(fentry, ss->ephoto->gadget_config->directory);
   elm_fileselector_buttons_ok_cancel_set(fentry, EINA_FALSE);
   elm_fileselector_folder_only_set(fentry, EINA_TRUE);
   evas_object_size_hint_weight_set(fentry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   evas_object_size_hint_align_set(fentry, EVAS_HINT_FILL, EVAS_HINT_FILL);
   elm_table_pack(table, fentry, 0, 0, 2, 5);
   evas_object_show(fentry);
   evas_object_data_set(popup, "fentry", fentry);

   label = elm_label_add(table);
   memset(buf, 0, PATH_MAX);
   snprintf(buf, PATH_MAX, "%s:", _("Show Each Slide For"));
   elm_object_text_set(label, buf);
   EPHOTO_FILL(label);
   elm_table_pack(table, label, 0, 5, 1, 1);
   evas_object_show(label);

   spinner = elm_spinner_add(table);
   elm_spinner_editable_set(spinner, EINA_TRUE);
   memset(buf, 0, PATH_MAX);
   snprintf(buf, PATH_MAX, "%%1.0f %s", _("seconds"));
   elm_spinner_label_format_set(spinner, buf);
   elm_spinner_step_set(spinner, 1);
   elm_spinner_value_set(spinner, ss->ephoto->gadget_config->slideshow_timeout);
   elm_spinner_min_max_set(spinner, 1, 60);
   elm_table_pack(table, spinner, 1, 5, 1, 1);
   evas_object_show(spinner);
   evas_object_data_set(popup, "timeout", spinner);

   but = elm_button_add(table);
   elm_object_text_set(but, _("Okay"));
   elm_table_pack(table, but, 0, 6, 2, 1);
   evas_object_smart_callback_add(but, "clicked", _gadget_settings_save, popup);
   evas_object_show(but);

   rect = evas_object_rectangle_add(evas_object_evas_get(table));
   evas_object_repeat_events_set(rect, EINA_TRUE);
   evas_object_color_set(rect, 0, 0, 0, 0);
   evas_object_size_hint_min_set(rect, 300, 300);
   elm_table_pack(table, rect, 0, 0, 2, 7);
   evas_object_show(rect);

   evas_object_show(popup);
}

static void
_key_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
          void *event_info)
{
   Ephoto_Slideshow *ss = data;
   Evas_Event_Key_Down *ev = event_info;
   const char *k = ev->keyname;

   if (ss->ephoto->state != EPHOTO_STATE_SLIDESHOW)
     return;

   if (!strcmp(k, "Escape") || !strcmp(k, "F5"))
     {
        if (!ss->ephoto->gadget)
          _back(ss, NULL, NULL);
     }
   else if (!strcmp(k, "F1"))
     {
        _settings(ss, NULL, NULL);
     }
   else if (!strcmp(k, "F11"))
     {
        _fullscreen(ss, NULL, NULL);
     }
   else if (!strcmp(k, "space"))
     {
        _pause(ss, NULL, NULL);
     }
   else if (!strcmp(k, "Home"))
     {
        _first(ss, NULL, NULL);
     }
   else if (!strcmp(k, "End"))
     {
        _last(ss, NULL, NULL);
     }
   else if (!strcmp(k, "Left"))
     {
        _previous(ss, NULL, NULL);
     }
   else if (!strcmp(k, "Right"))
     {
        _next(ss, NULL, NULL);
     }
}

static Evas_Object *
_add_icon(Evas_Object *parent, const char *icon, const char *label, Evas_Object *before)
{
   Evas_Object *ic, *but;
   int ret;

   ic = elm_icon_add(parent);
   evas_object_size_hint_min_set(ic, 20 * elm_config_scale_get(),
                                 20 * elm_config_scale_get());
   ret = elm_icon_standard_set(ic, icon);
   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_BOTH, 1, 1);

   but = elm_button_add(parent);
   if (!ret)
     elm_object_text_set(but, label);
   elm_object_part_content_set(but, "icon", ic);
   elm_object_tooltip_text_set(but, label);
   elm_object_tooltip_orient_set(but, ELM_TOOLTIP_ORIENT_TOP);

   if (before)
     elm_box_pack_before(parent, but, before);
   else
     elm_box_pack_end(parent, but);
   evas_object_show(but);

   return but;
}

static void
_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
          void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   if (ss->notify && ss->entry)
     {
        elm_notify_timeout_set(ss->notify, 0.0);
        evas_object_show(ss->notify);
     }
}

static void
_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
           void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   if (ss->notify && ss->entry)
     elm_notify_timeout_set(ss->notify, 3.0);
}

static void
_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
            void *event_info EINA_UNUSED)
{
   Ephoto_Slideshow *ss = data;

   if (ss->notify && ss->entry)
     {
        elm_notify_timeout_set(ss->notify, 3.0);
        evas_object_show(ss->notify);
     }
}

void
ephoto_slideshow_show_controls(Ephoto *ephoto)
{
   Ephoto_Slideshow *ss = evas_object_data_get(ephoto->slideshow, "slideshow");
   Evas_Object *but;

   ss->notify = elm_notify_add(ephoto->win);
   EPHOTO_EXPAND(ss->notify);

   ss->notify_box = elm_box_add(ss->notify);
   elm_box_horizontal_set(ss->notify_box, EINA_TRUE);
   EPHOTO_WEIGHT(ss->notify, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
   evas_object_event_callback_add(ss->notify_box, EVAS_CALLBACK_MOUSE_IN, _mouse_in,
                                  ss);
   evas_object_event_callback_add(ss->notify_box, EVAS_CALLBACK_MOUSE_OUT, _mouse_out,
                                  ss);
   elm_object_content_set(ss->notify, ss->notify_box);
   evas_object_show(ss->notify_box);

   if (ephoto->gadget)
     {
        but = _add_icon(ss->notify_box, "preferences-other", _("Settings"), NULL);
        evas_object_smart_callback_add(but, "clicked", _gadget_settings, ss);
        elm_notify_align_set(ss->notify, 0.5, 0.5);
        elm_notify_timeout_set(ss->notify, 0.0);
        evas_object_show(ss->notify);
        return;
     }
   but = _add_icon(ss->notify_box, "edit-undo", _("Back"), NULL);
   evas_object_smart_callback_add(but, "clicked", _back, ss);
   but = _add_icon(ss->notify_box, "go-first", _("First"), NULL);
   evas_object_smart_callback_add(but, "clicked", _first, ss);
   but = _add_icon(ss->notify_box, "go-previous", _("Previous"), NULL);
   evas_object_smart_callback_add(but, "clicked", _previous, ss);
   ss->pause =
     _add_icon(ss->notify_box, "media-playback-start", _("Play"), NULL);
   evas_object_smart_callback_add(ss->pause, "clicked", _pause, ss);
   ss->pause_after =
     _add_icon(ss->notify_box, "go-next", _("Next"), NULL);
   evas_object_smart_callback_add(ss->pause_after, "clicked", _next,
                                  ss);
   but = _add_icon(ss->notify_box, "go-last", _("Last"), NULL);
   evas_object_smart_callback_add(but, "clicked", _last, ss);
   ss->fullscreen =
     _add_icon(ss->notify_box, "view-fullscreen", _("Fullscreen"), NULL);
   evas_object_smart_callback_add(ss->fullscreen, "clicked", _fullscreen, ss);
   ss->fullscreen_after =
     _add_icon(ss->notify_box, "preferences-other", _("Settings"), NULL);
   evas_object_smart_callback_add(ss->fullscreen_after, "clicked", _settings, ss);
   ss->exit =
     _add_icon(ss->notify_box, "application-exit", _("Exit"), NULL);
   evas_object_smart_callback_add(ss->exit, "clicked", _fullscreen, ss);

   elm_box_unpack(ss->notify_box, ss->exit);
   evas_object_hide(ss->exit);

   elm_notify_align_set(ss->notify, 0.5, 1.0);
   elm_notify_timeout_set(ss->notify, 3.0);
   evas_object_show(ss->notify);
}

Evas_Object *
ephoto_slideshow_add(Ephoto *ephoto, Evas_Object *parent)
{
   Evas_Object *slideshow = elm_layout_add(parent);
   Ephoto_Slideshow *ss;

   EINA_SAFETY_ON_NULL_RETURN_VAL(slideshow, NULL);

   ss = calloc(1, sizeof(Ephoto_Slideshow));
   EINA_SAFETY_ON_NULL_GOTO(ss, error);
   ss->ephoto = ephoto;
   ss->slideshow = slideshow;
   ss->playing = 0;
   ss->current = 0;
   ss->notify = NULL;
   ss->notify_box = NULL;
   ss->old_item = NULL;
   ss->current_item = NULL;
   ss->event = NULL;
   ss->timer_end = EINA_TRUE;

   elm_layout_file_set(slideshow, PACKAGE_DATA_DIR "/themes/ephoto.edj",
                       "ephoto,slideshow,base");
   if (ephoto->gadget)
     elm_layout_signal_emit(slideshow, "gadget", "ephoto");
   evas_object_event_callback_add(slideshow, EVAS_CALLBACK_DEL, _slideshow_del,
                                  ss);
   if (!ephoto->gadget)
     evas_object_event_callback_add(slideshow, EVAS_CALLBACK_MOUSE_DOWN,
                                    _mouse_down, ss);
   evas_object_data_set(slideshow, "slideshow", ss);
   EPHOTO_EXPAND(slideshow);
   EPHOTO_FILL(slideshow);
   evas_object_event_callback_add(ss->slideshow, EVAS_CALLBACK_MOUSE_MOVE,
                                  _mouse_move, ss);
   edje_object_signal_callback_add(elm_layout_edje_get(ss->slideshow),
                                   "ephoto,transition,raise", "ephoto",
                                   _on_transition_raise, ss);
   edje_object_signal_callback_add(elm_layout_edje_get(ss->slideshow),
                                   "ephoto,transition,end", "ephoto",
                                   _on_transition_end, ss);
   return ss->slideshow;

error:
   evas_object_del(slideshow);
   return NULL;
}

void
ephoto_slideshow_entries_set(Evas_Object *obj, Eina_List *entries)
{
   Ephoto_Slideshow *ss = evas_object_data_get(obj, "slideshow");

   if (entries)
     ss->entries = entries;
   if (ss->ephoto->gadget)
     ephoto_slideshow_entry_set(ss->slideshow, eina_list_nth(ss->entries, 0));
}

void
ephoto_slideshow_entry_set(Evas_Object *obj, Ephoto_Entry *entry)
{
   Ephoto_Slideshow *ss = evas_object_data_get(obj, "slideshow");

   if (!entry)
     return;

   if (ss->entry)
     ephoto_entry_free_listener_del(ss->entry, _entry_free, ss);

   ss->entry = entry;
   ss->current = eina_list_data_idx(ss->entries, ss->entry);

   if (entry)
     ephoto_entry_free_listener_add(entry, _entry_free, ss);

   if (!ss->ephoto->gadget)
     ss->timeout = ss->ephoto->config->slideshow_timeout;
   else
     ss->timeout = ss->ephoto->gadget_config->slideshow_timeout;
   _slideshow_play(ss);
   ss->playing = 1;

   if (ss->pause)
     {
        evas_object_del(ss->pause);
        ss->pause =
          _add_icon(ss->notify_box, "media-playback-pause", _("Pause"),
                    ss->pause_after);
        evas_object_smart_callback_add(ss->pause, "clicked", _pause, ss);
        ss->playing = 1;
     }
   if (ss->fullscreen)
     {
        evas_object_del(ss->fullscreen);
        if (!elm_win_fullscreen_get(ss->ephoto->win))
          {
             ss->fullscreen =
               _add_icon(ss->notify_box, "view-fullscreen", _("Fullscreen"),
                         ss->fullscreen_after);
             evas_object_smart_callback_add(ss->fullscreen, "clicked",
                                            _fullscreen, ss);
             elm_box_unpack(ss->notify_box, ss->exit);
             evas_object_hide(ss->exit);
          }
        else
          {
             ss->fullscreen =
               _add_icon(ss->notify_box, "view-restore", _("Normal"),
                         ss->fullscreen_after);
             evas_object_smart_callback_add(ss->fullscreen, "clicked",
                                            _fullscreen, ss);
             elm_box_pack_end(ss->notify_box, ss->exit);
             evas_object_show(ss->exit);
          }
     }
   if (ss->event)
     {
        evas_object_del(ss->event);
        ss->event = NULL;
     }
   if (!ss->ephoto->gadget)
     {
        ss->event = evas_object_rectangle_add(ss->ephoto->win);
        evas_object_smart_member_add(ss->event, ss->ephoto->win);
        evas_object_color_set(ss->event, 0, 0, 0, 0);
        evas_object_repeat_events_set(ss->event, EINA_TRUE);
        evas_object_show(ss->event);
        evas_object_event_callback_add(ss->event, EVAS_CALLBACK_KEY_DOWN, _key_down,
                                  ss);
        evas_object_raise(ss->event);
        elm_object_focus_set(ss->event, EINA_TRUE);
     }
   else
     {
        if (ss->notify)
          {
             if (!elm_notify_timeout_get(ss->notify))
               {
                  elm_notify_timeout_set(ss->notify, 3.0);
                  evas_object_show(ss->notify);
               }
          }
     }
}

