/* vim: set sw=3 ts=3 sts=3 expandtab: */
#include "ecdb.h"
#include <dirent.h>
#include <Ecore_Str.h>

static void destroy_cb(Ewl_Widget *w, void *event, void *data);
static void conf_clicked_cb(Ewl_Widget *w, void *event, void *data);
static void scale_cb(Ewl_Widget *w, void *event, void *data);
static void fps_cb(Ewl_Widget *w, void *event, void *data);
static void engine_cb(Ewl_Widget *w, void *event, void *data);
static void theme_cb(Ewl_Widget *w, void *event, void *data);
static void combo_cb(Ewl_Widget *w, void *event, void *data);
static void del_cb(Ewl_Widget *w, void *event, void *data);
static void use_scale_cb(Ewl_Widget *w, void *event, void *data);
static Eina_List *theme_data_init(void);
static Eina_List *engine_data_init(void);
static int theme_data_return_active(Eina_List *data);
static int engine_data_return_active(Eina_List *data);
static unsigned int model_data_count(void *data);
static void *model_data_fetch(void *data, unsigned int row, unsigned int col);
static char *theme_cut_suffix(const char *file);

static Ewl_Widget *conf_win = NULL;

void
ecdb_config_dialog_show(void)
{
   Ewl_Widget *o, *l;
   Ewl_Widget *border_box, *hbox, *main_box;
   Ewl_Widget *combo;
   Ewl_Model *model;
   Ewl_View *view;
   Eina_List *data;
   int use_scale;

   /* Only show one config window */
   if (conf_win)
      return;

   conf_win = ewl_dialog_new();
   ewl_dialog_action_position_set(EWL_DIALOG(conf_win), EWL_POSITION_BOTTOM);
   ewl_window_title_set(EWL_WINDOW(conf_win), "ECDB Configuration");
   ewl_window_name_set(EWL_WINDOW(conf_win), "ECDB");
   ewl_window_class_set(EWL_WINDOW(conf_win), "ECDB");
   ewl_window_leader_foreign_set(EWL_WINDOW(conf_win),
                                                EWL_EMBED_WINDOW(em->xwin));
   ewl_callback_append(conf_win, EWL_CALLBACK_DELETE_WINDOW, destroy_cb, NULL);
   ewl_dialog_has_separator_set(EWL_DIALOG(conf_win), 1);
   ewl_object_fill_policy_set(EWL_OBJECT(conf_win), EWL_FLAG_FILL_NONE);
   ewl_widget_show(conf_win);

   /* the main_box contain the border_boxes */
   ewl_dialog_active_area_set(EWL_DIALOG(conf_win), EWL_POSITION_TOP);
   main_box = ewl_vbox_new();
   ewl_container_child_append(EWL_CONTAINER(conf_win), main_box);
   ewl_object_fill_policy_set(EWL_OBJECT(main_box), EWL_FLAG_FILL_FILL);
   ewl_widget_show(main_box);

   /* Setup and show the stock icons */
   ewl_dialog_active_area_set(EWL_DIALOG(conf_win), EWL_POSITION_BOTTOM);

   o = ewl_button_new();
   ewl_stock_type_set(EWL_STOCK(o), EWL_STOCK_CANCEL);
   ewl_container_child_append(EWL_CONTAINER(conf_win), o);
   ewl_callback_append(o, EWL_CALLBACK_CLICKED, conf_clicked_cb, conf_win);
   ewl_widget_show(o);

   o = ewl_button_new();
   ewl_stock_type_set(EWL_STOCK(o), EWL_STOCK_APPLY);
   ewl_container_child_append(EWL_CONTAINER(conf_win), o);
   ewl_callback_append(o, EWL_CALLBACK_CLICKED, conf_clicked_cb, conf_win);
   ewl_widget_show(o);

   o = ewl_button_new();
   ewl_stock_type_set(EWL_STOCK(o), EWL_STOCK_OK);
   ewl_container_child_append(EWL_CONTAINER(conf_win), o);
   ewl_callback_append(o, EWL_CALLBACK_CLICKED, conf_clicked_cb, conf_win);
   ewl_widget_show(o);

   /* Graphics */
   border_box = ewl_border_new();
   ewl_border_label_set(EWL_BORDER(border_box), "Graphics");
   ewl_container_child_append(EWL_CONTAINER(main_box), border_box);
   ewl_widget_show(border_box);

   /* Scale */
   hbox = ewl_grid_new();
   ewl_container_child_append(EWL_CONTAINER(border_box), hbox);
   ewl_object_fill_policy_set(EWL_OBJECT(hbox), EWL_FLAG_FILL_FILL);
   ewl_grid_column_preferred_w_use(EWL_GRID(hbox), 1);
   ewl_widget_show(hbox);

   o = ewl_label_new();
   ewl_label_text_set(EWL_LABEL(o), "Scale Factor:");
   ewl_container_child_append(EWL_CONTAINER(hbox), o);
   ewl_object_fill_policy_set(EWL_OBJECT(o), EWL_FLAG_FILL_NONE);
   ewl_object_alignment_set(EWL_OBJECT(o), EWL_FLAG_ALIGN_LEFT);
   ewl_widget_show(o);

   l = ewl_label_new();
   ewl_container_child_append(EWL_CONTAINER(hbox), l);
   ewl_object_fill_policy_set(EWL_OBJECT(l), EWL_FLAG_FILL_NONE);
   ewl_widget_show(l);

   use_scale = ecore_config_boolean_get("use_scale");

   o = ewl_hseeker_new();
   ewl_range_minimum_value_set(EWL_RANGE(o), 0.0);
   ewl_range_maximum_value_set(EWL_RANGE(o), 2.0);
   ewl_range_step_set(EWL_RANGE(o), 0.25);
   ewl_range_value_set(EWL_RANGE(o), em->scalef);
   ewl_container_child_append(EWL_CONTAINER(border_box), o);
   ewl_callback_append(o, EWL_CALLBACK_VALUE_CHANGED, scale_cb, l);
   if (!use_scale)
      ewl_widget_disable(o);
   scale_cb(o, NULL, l);
   ewl_widget_show(o);

   // Store this widget as we use it as a parameter later
   l = o;

   o = ewl_checkbutton_new();
   ewl_button_label_set(EWL_BUTTON(o), "Use scaling?");
   ewl_container_child_append(EWL_CONTAINER(border_box), o);
   ewl_object_alignment_set(EWL_OBJECT(o), EWL_FLAG_ALIGN_LEFT);
   ewl_togglebutton_checked_set(EWL_TOGGLEBUTTON(o), use_scale);
   ewl_widget_show(o);
   ewl_callback_append(o, EWL_CALLBACK_CLICKED, use_scale_cb, l);

   /* FPS */
   hbox = ewl_grid_new();
   ewl_container_child_append(EWL_CONTAINER(border_box), hbox);
   ewl_object_fill_policy_set(EWL_OBJECT(hbox), EWL_FLAG_FILL_ALL);
   ewl_grid_column_preferred_w_use(EWL_GRID(hbox), 1);
   ewl_widget_show(hbox);

   o = ewl_label_new();
   ewl_label_text_set(EWL_LABEL(o), "Frame Rate:");
   ewl_container_child_append(EWL_CONTAINER(hbox), o);
   ewl_object_fill_policy_set(EWL_OBJECT(o), EWL_FLAG_FILL_NONE);
   ewl_object_alignment_set(EWL_OBJECT(o), EWL_FLAG_ALIGN_LEFT);
   ewl_widget_show(o);

   l = ewl_label_new();
   ewl_container_child_append(EWL_CONTAINER(hbox), l);
   ewl_object_fill_policy_set(EWL_OBJECT(l), EWL_FLAG_FILL_NONE);
   ewl_widget_show(l);

   o = ewl_hseeker_new();
   ewl_range_minimum_value_set(EWL_RANGE(o), 10.0);
   ewl_range_maximum_value_set(EWL_RANGE(o), 100.0);
   ewl_range_step_set(EWL_RANGE(o), 15.0);
   ewl_range_value_set(EWL_RANGE(o), em->fps);
   ewl_container_child_append(EWL_CONTAINER(border_box), o);
   ewl_callback_append(o, EWL_CALLBACK_VALUE_CHANGED, fps_cb, l);
   fps_cb(o, NULL, l);
   ewl_widget_show(o);

   /* Setup and show the border box */
   border_box = ewl_border_new();
   ewl_border_label_set(EWL_BORDER(border_box), "Rendering Engine");
   ewl_container_child_append(EWL_CONTAINER(main_box), border_box);
   ewl_object_fill_policy_set(EWL_OBJECT(border_box), EWL_FLAG_FILL_NORMAL);
   ewl_object_alignment_set(EWL_OBJECT(border_box), EWL_FLAG_ALIGN_CENTER);
   ewl_object_alignment_set(EWL_OBJECT(main_box), EWL_FLAG_ALIGN_TOP);
   ewl_widget_show(border_box);

   model = ewl_model_new();
   ewl_model_data_fetch_set(model, model_data_fetch);
   ewl_model_data_count_set(model, model_data_count);

   view = ewl_label_view_get();

   data = engine_data_init();

   combo = ewl_combo_new();
   ewl_container_child_append(EWL_CONTAINER(border_box), combo);
   ewl_callback_append(combo, EWL_CALLBACK_VALUE_CHANGED, engine_cb, NULL);
   ewl_callback_append(combo, EWL_CALLBACK_DESTROY, combo_cb, data);
   ewl_callback_append(combo, EWL_CALLBACK_DESTROY, del_cb, view);
   ewl_callback_append(combo, EWL_CALLBACK_DESTROY, del_cb, model);
   ewl_mvc_model_set(EWL_MVC(combo), model);
   ewl_mvc_view_set(EWL_MVC(combo), view);
   ewl_mvc_data_set(EWL_MVC(combo), data);
   ewl_mvc_selected_set(EWL_MVC(combo), model, data,
                                          engine_data_return_active(data), 0);
   ewl_widget_show(combo);

   /* Setup and show the border box */
   border_box = ewl_border_new();
   ewl_border_label_set(EWL_BORDER(border_box), "Theme");
   ewl_container_child_append(EWL_CONTAINER(main_box), border_box);
   ewl_object_fill_policy_set(EWL_OBJECT(border_box), EWL_FLAG_FILL_FILL);
   ewl_object_alignment_set(EWL_OBJECT(border_box), EWL_FLAG_ALIGN_CENTER);
   ewl_object_alignment_set(EWL_OBJECT(main_box), EWL_FLAG_ALIGN_TOP);
   ewl_widget_show(border_box);

   data = theme_data_init();

   combo = ewl_combo_new();
   ewl_container_child_append(EWL_CONTAINER(border_box), combo);
   ewl_callback_append(combo, EWL_CALLBACK_VALUE_CHANGED, theme_cb, NULL);
   ewl_callback_append(combo, EWL_CALLBACK_DESTROY, combo_cb, data);
   ewl_mvc_model_set(EWL_MVC(combo), model);
   ewl_mvc_view_set(EWL_MVC(combo), view);
   ewl_mvc_data_set(EWL_MVC(combo), data);
   ewl_mvc_selected_set(EWL_MVC(combo), model, data,
                                          theme_data_return_active(data), 0);
   ewl_widget_show(combo);
}

static void
destroy_cb(Ewl_Widget *w, void *event __UNUSED__, void *data __UNUSED__)
{
   ewl_widget_destroy(w);
   conf_win = NULL;
}

static void
conf_clicked_cb(Ewl_Widget *w, void *event __UNUSED__, void *data)
{
   Ewl_Stock_Type response;

   response = ewl_stock_type_get(EWL_STOCK(w));

   if ((response == EWL_STOCK_OK) || (response == EWL_STOCK_APPLY))
   {
      if (ecore_config_save() != ECORE_CONFIG_ERR_SUCC)
         EINA_ERROR_PWARN("Failure to save configuration!\n");
   }

   if ((response == EWL_STOCK_OK) || (response == EWL_STOCK_CANCEL))
   {
      ewl_widget_destroy(EWL_WIDGET(data));
      conf_win = NULL;
   }
}

static void
scale_cb(Ewl_Widget *w, void *event __UNUSED__, void *data)
{
   double value;
   char buffer[10];

   value = ewl_range_value_get(EWL_RANGE(w));
   ecore_config_float_set("scale", value);
   snprintf(buffer, 10, "%.1f", value);
   ewl_label_text_set(EWL_LABEL(data), buffer);
}

static void
fps_cb(Ewl_Widget *w, void *event __UNUSED__, void *data)
{
   int value;
   char buffer[10];

   value = ewl_range_value_get(EWL_RANGE(w));
   ecore_config_int_set("frame_rate", value);
   snprintf(buffer, 10, "%d", value);
   ewl_label_text_set(EWL_LABEL(data), buffer);
}

static void
engine_cb(Ewl_Widget *w, void *event __UNUSED__, void *data)
{
   Eina_List *l;
   Ewl_Selection_Idx *idx;
   char *eng;

   l = ewl_mvc_data_get(EWL_MVC(w));
   idx = ewl_mvc_selected_get(EWL_MVC(w));
   if (!idx)
      return;
   free(em->engine);
   
   eng = eina_list_nth(l, idx->row);
   ecore_config_string_set("engine", eng);
   em->engine = strdup(eng);
   free(idx);
}

static void
theme_cb(Ewl_Widget *w, void *event __UNUSED__, void *data)
{
   Eina_List *l;
   Ewl_Selection_Idx *idx;
   char *theme;

   l = ewl_mvc_data_get(EWL_MVC(w));
   idx = ewl_mvc_selected_get(EWL_MVC(w));
   if (!idx)
      return;

   theme = eina_list_nth(l, idx->row);

   if (strcmp(theme, ecore_config_theme_get("theme")))
   {
      free(em->theme_path);
      ecore_config_theme_set("theme", theme);
      em->theme_path = ecore_config_theme_with_path_get("theme");
   }
   free(idx);
}

static Eina_List *
theme_data_init(void)
{
   Eina_List *ret = NULL;
   char *dirs;
   char **dirs_array;
   struct dirent *file;
   DIR *rep;
   int i = 0;

   dirs = ecore_config_theme_search_path_get();
   dirs_array = ecore_str_split(dirs, "|", -1);
   free(dirs);

   if (!dirs_array)
   {
      EINA_ERROR_PWARN("No possible theme paths!\n");
      return NULL;
   }

   while ((dirs = dirs_array[i]))
   {
      rep = opendir(dirs);
      if (rep)
      {
         while ((file = readdir(rep)))
         {
            if ((strlen(file->d_name) > 4) &&
                                 (ecore_str_has_suffix(file->d_name, ".edj")))
               ret = eina_list_append(ret, theme_cut_suffix(file->d_name));
         }
         closedir(rep);
      }
      i++;
   }

   free(*dirs_array);
   free(dirs_array);

   if (!ret)
   {
      EINA_ERROR_PWARN("No themes available!\n");
      return NULL;
   }

   return ret;
}

static int
theme_data_return_active(Eina_List *l)
{
   int i;
   char *theme, *tmp_theme;

   theme = ecore_config_theme_get("theme");

   EINA_LIST_FOREACH(l, l, tmp_theme)
   {
      if (!strcmp(tmp_theme, theme))
         break;
      i++;
   }

   free(theme);
   return i;
}

static Eina_List *
engine_data_init(void)
{
   Eina_List *l, *ret = NULL;
   char *eng;
   int i;
   const char *accepted_engines[] = {"software_x11", "xrender_x11",
                                     "opengl_x11", NULL};

   l = ecore_evas_engines_get();

   EINA_LIST_FOREACH(l, l, eng)
   {
      for (i = 0; accepted_engines[i]; i++)
      {
         if (!strcmp(accepted_engines[i], eng))
         {
            ret = eina_list_append(ret, strdup(eng));
            break;
         }
      }
   }

   ecore_evas_engines_free(l);

   return ret;
}

static int
engine_data_return_active(Eina_List *l)
{
   int i = 0;
   char *eng, *tmp_eng;

   eng = ecore_config_string_get("engine");

   EINA_LIST_FOREACH(l, l, tmp_eng)
   {
      if (!strcmp(tmp_eng, eng))
         break;
      i++;
   }

   free(eng);
   return i;
}

static unsigned int
model_data_count(void *data)
{
   Eina_List *l = data;
   return eina_list_count(l);
}

static void *
model_data_fetch(void *data, unsigned int row, unsigned int col __UNUSED__)
{
   Eina_List *l = data;
   return eina_list_nth(l, row);
}

static char *
theme_cut_suffix(const char *file)
{
   char *new_file, *pt, *end;

   end = strrchr(file, '.');

   new_file = malloc(end - file + 1);
   pt = new_file;

   while (file != end)
      *pt++ = *file++;
   
   *pt = '\0';

   return new_file;
}

static void
combo_cb(Ewl_Widget *w, void *event __UNUSED__, void *data)
{
   char *str;

   EINA_LIST_FREE(data, str)
      free(str);
}

static void
use_scale_cb(Ewl_Widget *w, void *event __UNUSED__, void *data)
{
   int use_scale;

   use_scale = ewl_togglebutton_checked_get(EWL_TOGGLEBUTTON(w));
   ecore_config_boolean_set("use_scale", use_scale);

   if (use_scale)
      ewl_widget_enable(EWL_WIDGET(data));
   else
      ewl_widget_disable(EWL_WIDGET(data));
}

static void
del_cb(Ewl_Widget *w __UNUSED__, void *event __UNUSED__, void *data)
{
   FREE(data);
}