/*
 * This file is part of GNAC - Gnome Audio Converter
 *
 * Copyright (C) 2007 - 2012 Gnac
 *    
 *    - DUPASQUIER  Benoit    <bdupasqu@src.gnome.org>
 *    - JOAQUIM     David     <djoaquim@src.gnome.org>
 *    - ROUX        Alexandre <alexroux@src.gnome.org>
 *
 * GNAC is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * GNAC is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GNAC; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, 
 * Boston, MA  02110-1301  USA
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <glib/gi18n.h>

#include "gnac-file-list.h"
#include "gnac-main.h"
#include "gnac-prefs.h"
#include "gnac-properties.h"
#include "gnac-settings.h"
#include "gnac-ui.h"
#include "gnac-ui-utils.h"
#include "gnac-utils.h"

#include "libgnac-output.h"

#include "profiles/gnac-profiles.h"

static GtkBuilder *gnac_prefs_builder = NULL;

static gchar *tooltip_patterns = NULL;

const gchar *rename_pattern_default[] = {
  "\%f",
  "\%t",
  "\%a - \%t",
  "\%a - \%b - \%t",
  "\%n - \%t",
  "\%n - \%a - \%t",
  "\%n - \%a - \%b - \%t",
  "\%a - \%n - \%t",
};

const gchar *folder_hierarchy_default[] = {
  "",
  "\%a",
  "\%b",
  "\%a - \%b",
  "\%a/\%b",
  "\%a/\%b (\%y)",
};

static gchar *
gnac_prefs_get_folder_hierarchy_as_str(void);

static gchar *
gnac_prefs_get_rename_pattern_as_str(void);

static void
gnac_prefs_select_custom_pattern(GtkComboBox *combo_box);


static gchar *
gnac_prefs_get_tooltip_patterns(void)
{
  if (!tooltip_patterns) {
    /* Translators: patterns refers to rename patterns, e.g., %a -> artist */
    tooltip_patterns = g_strconcat(_("Patterns available:"),
        "\n  <b>\%a:</b> ", _("Artist"),
        "\n  <b>\%b:</b> ", _("Album"),
        "\n  <b>\%c:</b> ", _("Comment"),
        "\n  <b>\%d:</b> ", _("Disc number"),
        "\n  <b>\%e:</b> ", _("Disc count"),
        "\n  <b>\%f:</b> ", _("Filename"),
        "\n  <b>\%g:</b> ", _("Genre"),
        "\n  <b>\%t:</b> ", _("Title"),
        "\n  <b>\%l:</b> ", _("Track count"),
        "\n  <b>\%n:</b> ", _("Track number"),
        "\n  <b>\%y:</b> ", _("Year"),
        NULL);
  }

  return tooltip_patterns;
}


static void
gnac_prefs_free_tooltip_patterns(void)
{
  g_free(tooltip_patterns);
}


static GtkWidget *
gnac_prefs_get_widget(const gchar *widget_name)
{
  return gnac_ui_utils_get_widget(gnac_prefs_builder, widget_name);
}


static const gchar *
gnac_prefs_entry_get_text(const gchar *entry_name)
{
  GtkEntry *entry = GTK_ENTRY(gnac_prefs_get_widget(entry_name));
  return gtk_entry_get_text(entry);
}


static void
gnac_prefs_entry_set_text(const gchar *entry_name,
                          const gchar *text)
{
  GtkEntry *entry = GTK_ENTRY(gnac_prefs_get_widget(entry_name));
  gtk_entry_set_text(entry, text);
}


static void
gnac_prefs_set_widget_sensitive(const gchar *widget_name,
                                gboolean     sensitive)
{
  gnac_ui_utils_set_widget_sensitive(gnac_prefs_builder, widget_name, sensitive);
}


static void
gnac_prefs_set_event_box_above_child(const gchar *box_name,
                                     gboolean     above_child)
{
  GtkEventBox *event_box = GTK_EVENT_BOX(gnac_prefs_get_widget(box_name));
  gtk_event_box_set_above_child(event_box, above_child);
}


static gint
gnac_prefs_get_combo_box_active(const gchar *box_name)
{
  GtkComboBox *combo_box = GTK_COMBO_BOX(gnac_prefs_get_widget(box_name));
  return gtk_combo_box_get_active(combo_box);
}


static void
gnac_prefs_set_combo_box_active(const gchar *box_name,
                                gint         index)
{
  GtkComboBox *combo_box = GTK_COMBO_BOX(gnac_prefs_get_widget(box_name));
  return gtk_combo_box_set_active(combo_box, index);
}


static void
gnac_prefs_set_toggle_button_active(const gchar *button_name,
                                    gboolean     is_active)
{
  GtkToggleButton *button = GTK_TOGGLE_BUTTON(gnac_prefs_get_widget(button_name));
  gtk_toggle_button_set_active(button, is_active);
}


static void 
gnac_prefs_set_same_mode(void)
{
  gnac_prefs_set_event_box_above_child("selected_eventbox", TRUE);
  gnac_prefs_set_event_box_above_child("subfolder_eventbox", TRUE);

  gnac_prefs_set_widget_sensitive("filechooserbutton", FALSE);
  gnac_prefs_set_widget_sensitive("subfolder_entry", FALSE);
  gnac_prefs_set_widget_sensitive("subfolder_label", FALSE);
  gnac_prefs_set_widget_sensitive("selected_label", FALSE);
}


static void
gnac_prefs_set_subfolder_mode(void)
{
  gnac_prefs_set_event_box_above_child("selected_eventbox", TRUE);

  gnac_prefs_set_widget_sensitive("filechooserbutton", FALSE);
  gnac_prefs_set_widget_sensitive("subfolder_entry", TRUE);
  gnac_prefs_set_widget_sensitive("subfolder_label", TRUE);
  gnac_prefs_set_widget_sensitive("selected_label", FALSE);
}


static void
gnac_prefs_set_selected_mode(void)
{
  gnac_prefs_set_event_box_above_child("subfolder_eventbox", TRUE);

  gnac_prefs_set_widget_sensitive("filechooserbutton", TRUE);
  gnac_prefs_set_widget_sensitive("subfolder_entry", FALSE);
  gnac_prefs_set_widget_sensitive("subfolder_label", FALSE);
  gnac_prefs_set_widget_sensitive("selected_label", TRUE);
}


static void
gnac_prefs_retrieve_settings(void)
{
  gchar *str;

  gnac_prefs_set_combo_box_active("output_filename_combo",
      gnac_settings_get_int(GNAC_KEY_RENAME_PATTERN));

  str = gnac_prefs_get_rename_pattern_as_str();
  gnac_prefs_entry_set_text("output_filename_entry", str);
  g_free(str);

  gnac_prefs_set_combo_box_active("folder_hierarchy_combo",
      gnac_settings_get_int(GNAC_KEY_FOLDER_HIERARCHY));

  str = gnac_prefs_get_folder_hierarchy_as_str();
  gnac_prefs_entry_set_text("folder_hierarchy_entry", str);
  g_free(str);

  switch (gnac_settings_get_int(GNAC_KEY_FOLDER_TYPE))
  {
    case FOLDER_SUBDIRECTORY:
      str = gnac_settings_get_string(GNAC_KEY_DESTINATION_DIRECTORY);
      gnac_prefs_entry_set_text("subfolder_entry", str);
      g_free(str);
      gnac_prefs_set_toggle_button_active("subfolder_radiobutton", TRUE);
      gnac_prefs_set_subfolder_mode();
    break;

    case FOLDER_SELECTED:
      str = gnac_settings_get_string(GNAC_KEY_DESTINATION_DIRECTORY);
      gtk_file_chooser_select_uri(
          GTK_FILE_CHOOSER(gnac_prefs_get_widget("filechooserbutton")), str);
      g_free(str);
      gnac_prefs_set_toggle_button_active("selected_radiobutton", TRUE);
      gnac_prefs_set_selected_mode();
    break;

    /* Same as source */
    case FOLDER_CURRENT:
    default:
      gnac_prefs_set_toggle_button_active("same_radiobutton", TRUE);
      gnac_prefs_set_same_mode();
    break;
  }
}


static void
gnac_prefs_set_parent(void)
{
  GtkWidget *window = gnac_prefs_get_widget("gnac_preference_window");
  GtkWidget *parent = gnac_ui_get_widget("main_window");
  gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(parent));
}


static void
gnac_prefs_init_gsettings_bindings(void)
{
  gnac_settings_ui_bind(GNAC_KEY_TRAY_ICON,
      gnac_prefs_get_widget("check_notification_icon"));

  gnac_settings_bind(GNAC_KEY_CLEAR_SOURCE,
      gnac_prefs_get_widget("erase_originals_checkbutton"));

  gnac_settings_bind(GNAC_KEY_STRIP_SPECIAL,
      gnac_prefs_get_widget("strip_special_checkbutton"));
}


static void
gnac_prefs_init(void)
{
  gnac_prefs_builder = gnac_ui_utils_create_gtk_builder(
      PKGDATADIR "/gnac-pref-window.xml");

  gnac_prefs_set_parent();
  gnac_prefs_init_gsettings_bindings();
}


static void
gnac_prefs_select_general_tab(void)
{
  GtkWidget *notebook = gnac_prefs_get_widget("notebook");
  gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);
}


void
gnac_prefs_window_show(void)
{
  if (G_UNLIKELY(!gnac_prefs_builder)) {
    gnac_prefs_init();
  }

  gnac_prefs_retrieve_settings();
  gnac_prefs_select_general_tab();

  GtkWidget *prefs_window = gnac_prefs_get_widget("gnac_preference_window");
  gtk_widget_show_all(prefs_window);
  gtk_window_present(GTK_WINDOW(prefs_window));
}


static gchar *
gnac_prefs_get_rename_pattern_as_str(void)
{
  gint index = gnac_prefs_get_combo_box_active("output_filename_combo");
  gint size = G_N_ELEMENTS(rename_pattern_default);

  g_assert(index >= 0 && index <= size);

  if (index == size) {
    return gnac_settings_get_string(GNAC_KEY_RENAME_PATTERN_PATTERN);
  }

  return g_strdup(rename_pattern_default[index]);
}


static gchar *
gnac_prefs_get_folder_hierarchy_as_str(void)
{
  gint index = gnac_prefs_get_combo_box_active("folder_hierarchy_combo");
  gint size = G_N_ELEMENTS(folder_hierarchy_default);

  g_assert(index >= 0 && index <= size);

  if (index == size) {
    return gnac_settings_get_string(GNAC_KEY_FOLDER_HIERARCHY_PATTERN);
  }

  return g_strdup(folder_hierarchy_default[index]);
}


void
gnac_prefs_same_radio_toggled(GtkWidget *widget,
                              gpointer   data)
{
  gnac_prefs_set_same_mode();
  gnac_settings_set_int(GNAC_KEY_FOLDER_TYPE, FOLDER_CURRENT);
  gnac_settings_set_string(GNAC_KEY_DESTINATION_DIRECTORY, "");
}


void
gnac_prefs_strip_special_toggled(GtkWidget *widget,
                                 gpointer   data)
{
  gnac_prefs_update_example_label(widget, data);
}


void
gnac_prefs_subfolder_radio_toggled(GtkWidget *widget,
                                   gpointer   data)
{ 
  gnac_prefs_set_subfolder_mode();
  gnac_settings_set_int(GNAC_KEY_FOLDER_TYPE, FOLDER_SUBDIRECTORY);
  const gchar *subfolder = gnac_prefs_entry_get_text("subfolder_entry");
  gnac_settings_set_string(GNAC_KEY_DESTINATION_DIRECTORY, subfolder);
}


void
gnac_prefs_subfolder_editing_done(GtkWidget *widget,
                                  gpointer   data)
{
  const gchar *subfolder = gtk_entry_get_text(GTK_ENTRY(widget));
  gnac_settings_set_string(GNAC_KEY_DESTINATION_DIRECTORY, subfolder);
}


void
gnac_prefs_selected_radio_toggled(GtkWidget *widget,
                                  gpointer   data)
{
  GtkWidget *filechooserbutton = gnac_prefs_get_widget("filechooserbutton");
  gnac_prefs_set_selected_mode();
  gnac_settings_set_int(GNAC_KEY_FOLDER_TYPE, FOLDER_SELECTED);
  gchar *uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(filechooserbutton));
  gnac_settings_set_string(GNAC_KEY_DESTINATION_DIRECTORY, uri);
  g_free(uri);
}


void
gnac_prefs_selected_uri_changed(GtkWidget *widget,
                                gpointer   data)
{
  GtkWidget *filechooserbutton = gnac_prefs_get_widget("filechooserbutton");
  gchar *uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(filechooserbutton));
  gnac_settings_set_string(GNAC_KEY_DESTINATION_DIRECTORY, uri);
  g_free(uri);
}


void
gnac_prefs_update_example_label(GtkWidget *widget,
                                gpointer   data)
{
  const gchar *pattern_filename = gnac_prefs_entry_get_text(
      "output_filename_entry");
  if (!gnac_utils_string_is_null_or_empty(pattern_filename))
  {
    gnac_settings_set_string(GNAC_KEY_RENAME_PATTERN_PATTERN, pattern_filename);
  }

  gchar *pattern;
  GtkWidget *combo = gnac_prefs_get_widget("folder_hierarchy_combo");

  if (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)) != 0) {
    const gchar *pattern_folder = gnac_prefs_entry_get_text(
        "folder_hierarchy_entry");
    if (gnac_utils_string_is_null_or_empty(pattern_folder)) {
      pattern = g_strdup(pattern_filename);
    } else {
      gnac_settings_set_string(GNAC_KEY_FOLDER_HIERARCHY_PATTERN,
          pattern_folder);
      pattern = g_strdup_printf("%s/%s", pattern_folder, pattern_filename);
    }
  } else {
    pattern = g_strdup(pattern_filename);
  }

  gchar *preview = libgnac_output_get_preview_from_pattern(pattern,
      gnac_settings_get_boolean(GNAC_KEY_STRIP_SPECIAL));
  g_free(pattern);
  gchar *clean_label = g_markup_printf_escaped("%s.%s",
      preview, gnac_profiles_get_extension());
  g_free(preview);

  GtkWidget *label = gnac_prefs_get_widget("example_label");
  gtk_label_set_markup(GTK_LABEL(label), clean_label);
  g_free(clean_label);
}


gboolean
gnac_prefs_button_press_event_cb(GtkWidget      *widget, 
                                 GdkEventButton *event, 
                                 gpointer        user_data)
{
  if (!gnac_ui_utils_event_is_left_click(event)) return FALSE;

  GtkWidget *child = gtk_bin_get_child(GTK_BIN(user_data));
  GType widget_type = G_OBJECT_TYPE(widget);

  if (widget_type == GTK_TYPE_COMBO_BOX) {
    gnac_prefs_select_custom_pattern(GTK_COMBO_BOX(widget));
  } else if (widget_type == GTK_TYPE_RADIO_BUTTON) {
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
  }

  gtk_event_box_set_above_child(GTK_EVENT_BOX(user_data), FALSE);
  gtk_widget_set_sensitive(child, TRUE);
  gtk_widget_grab_focus(child);
  
  return TRUE;
}


static gboolean
gnac_prefs_custom_pattern_is_selected(GtkComboBox *combo_box,
                                      gint         selected_index)
{
  gint size = gnac_ui_utils_get_combo_size(combo_box);
  return (selected_index == size-1);
}


static void
gnac_prefs_select_custom_pattern(GtkComboBox *combo_box)
{
  gint size = gnac_ui_utils_get_combo_size(combo_box);
  gtk_combo_box_set_active(combo_box, size-1);
}


void
gnac_prefs_pattern_changed_cb(GtkWidget *widget,
                              gpointer   data)
{
  gnac_prefs_update_example_label(widget, data);

  gint selected_index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
  gboolean is_custom_pattern = gnac_prefs_custom_pattern_is_selected(
      GTK_COMBO_BOX(widget), selected_index);

  gnac_prefs_set_event_box_above_child("output_filename_eventbox",
      !is_custom_pattern);

  GtkWidget *filename_entry = gnac_prefs_get_widget("output_filename_entry");
  gtk_widget_set_sensitive(filename_entry, is_custom_pattern);

  gchar *pattern = gnac_prefs_get_rename_pattern_as_str();
  gtk_entry_set_text(GTK_ENTRY(filename_entry), pattern);

  gnac_settings_set_int(GNAC_KEY_RENAME_PATTERN, selected_index);
  gnac_settings_set_string(GNAC_KEY_RENAME_PATTERN_PATTERN, pattern);

  g_free(pattern);
}


void
gnac_prefs_folder_hierarchy_changed_cb(GtkWidget *widget,
                                       gpointer   data)
{
  gnac_prefs_update_example_label(widget, data);

  gint selected_index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
  GtkWidget *folder_entry = gnac_prefs_get_widget("folder_hierarchy_entry");
  gboolean is_custom_pattern = gnac_prefs_custom_pattern_is_selected(
      GTK_COMBO_BOX(widget), selected_index);

  gnac_prefs_set_event_box_above_child("folder_hierarchy_eventbox",
      !is_custom_pattern);
  gtk_widget_set_sensitive(folder_entry, is_custom_pattern);

  gchar *pattern = gnac_prefs_get_folder_hierarchy_as_str();
  gtk_entry_set_text(GTK_ENTRY(folder_entry), pattern);

  gnac_settings_set_int(GNAC_KEY_FOLDER_HIERARCHY, selected_index);
  gnac_settings_set_string(GNAC_KEY_FOLDER_HIERARCHY_PATTERN, pattern);

  g_free(pattern);
}


gboolean
gnac_prefs_query_tooltip_cb(GtkWidget  *entry,
                            gint        x,
                            gint        y,
                            gboolean    keyboard_mode,
                            GtkTooltip *tooltip,
                            gpointer    user_data)
{
  gtk_tooltip_set_markup(tooltip, gnac_prefs_get_tooltip_patterns());
  return TRUE;
}


static void
gnac_prefs_window_hide(void)
{
  if (G_LIKELY(gnac_prefs_builder)) {
    GtkWidget *prefs_window = gnac_prefs_get_widget("gnac_preference_window");
    gtk_widget_hide(prefs_window);
  }
}


void
gnac_prefs_on_close(GtkWidget *widget,
                    gpointer   data)
{
  gnac_prefs_window_hide();
}


void
gnac_prefs_destroy(void)
{  
  if (gnac_prefs_builder) {
    GtkWidget *window = gnac_prefs_get_widget("gnac_preference_window");
    gtk_widget_destroy(window);
    g_object_unref(gnac_prefs_builder);
    gnac_prefs_builder = NULL;
  }

  gnac_prefs_free_tooltip_patterns();
}
