/* OGMRip - A DVD Encoder for GNOME
 * Copyright (C) 2004-2012 Olivier Rolland <billl@users.sourceforge.net>
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

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

#include "ogmrip-gconf.h"
#include "ogmrip-helper.h"
#include "ogmrip-plugin.h"
#include "ogmrip-profiles.h"
#include "ogmrip-options-plugin.h"
#include "ogmrip-profile-editor.h"
#include "ogmrip-profiles-dialog.h"
#include "ogmrip-settings.h"

#include <glib/gi18n.h>
#include <glade/glade.h>

#define OGMRIP_GLADE_FILE "ogmrip" G_DIR_SEPARATOR_S "ogmrip-profile-editor.glade"
#define OGMRIP_GLADE_ROOT "root"

#define OGMRIP_PROFILE_EDITOR_DIALOG_GET_PRIVATE(o) \
  (G_TYPE_INSTANCE_GET_PRIVATE ((o), OGMRIP_TYPE_PROFILE_EDITOR_DIALOG, OGMRipProfileEditorDialogPriv))

struct _OGMRipProfileEditorDialogPriv
{
  GtkWidget *root;

  GtkWidget *video_codec_combo;
  GtkWidget *audio_codec_combo;
  GtkWidget *subp_codec_combo;

  GtkWidget *container_options_button;
  GtkWidget *video_options_button;
  GtkWidget *audio_options_button;
  GtkWidget *subp_options_button;

  GtkWidget *encoding_label;
  GtkWidget *encoding_combo;
  GtkWidget *encoding_table;

  GtkWidget *bitrate_label;
  GtkWidget *bitrate_hbox;

  GtkWidget *quantizer_spin;
  GtkWidget *quantizer_label;

  GtkWidget *target_label;
  GtkWidget *target_hbox;

  GtkWidget *video_preset_label;
  GtkWidget *video_preset_hbox;
  GtkWidget *video_preset_combo;

  GtkWidget *passes_label;
  GtkWidget *passes_spin;
  GtkWidget *passes_hbox;

  GtkWidget *video_options_label;
  GtkWidget *video_options_vbox;

  GtkWidget *audio_quality_label;
  GtkWidget *audio_quality_spin;

  GtkWidget *audio_options_label;
  GtkWidget *audio_options_table;

  GtkWidget *subp_options_label;
  GtkWidget *subp_options_table;

  GtkWidget *scale_box;
  GtkWidget *video_expander;

  GtkWidget *expand_check;

  gchar *profile_section;
};

enum
{
  SIZE,
  BITRATE,
  QUANTIZER
};

static void ogmrip_profile_editor_dialog_finalize (GObject *gobject);

static const gchar *_profile_section;

extern OGMRipSettings *settings;

static GType
ogmrip_profile_editor_dialog_get_container_type (OGMRipProfileEditorDialog *dialog, const gchar *name)
{
  GType container;

  if (name)
    container = ogmrip_plugin_get_container_by_name (name);
  else
  {
    gchar *format;

    ogmrip_settings_get (settings, dialog->priv->profile_section,
        OGMRIP_GCONF_CONTAINER_FORMAT, &format, NULL);
    container = ogmrip_plugin_get_container_by_name (format);
    g_free (format);
  }

  return container;
}

static GType
ogmrip_profile_editor_dialog_get_video_codec_type (OGMRipProfileEditorDialog *dialog, const gchar *name)
{
  GType container;

  if (name)
    container = ogmrip_plugin_get_video_codec_by_name (name);
  else
  {
    gchar *codec;

    ogmrip_settings_get (settings, dialog->priv->profile_section,
        OGMRIP_GCONF_VIDEO_CODEC, &codec, NULL);
    container = ogmrip_plugin_get_video_codec_by_name (codec);
    g_free (codec);
  }

  return container;
}

static GType
ogmrip_profile_editor_dialog_get_audio_codec_type (OGMRipProfileEditorDialog *dialog, const gchar *name)
{
  GType container;

  if (name)
    container = ogmrip_plugin_get_audio_codec_by_name (name);
  else
  {
    gchar *codec;

    ogmrip_settings_get (settings, dialog->priv->profile_section,
        OGMRIP_GCONF_AUDIO_CODEC, &codec, NULL);
    container = ogmrip_plugin_get_audio_codec_by_name (codec);
    g_free (codec);
  }

  return container;
}

static GType
ogmrip_profile_editor_dialog_get_subp_codec_type (OGMRipProfileEditorDialog *dialog, const gchar *name)
{
  GType container;

  if (name)
    container = ogmrip_plugin_get_subp_codec_by_name (name);
  else
  {
    gchar *codec;

    ogmrip_settings_get (settings, dialog->priv->profile_section,
        OGMRIP_GCONF_SUBP_CODEC, &codec, NULL);
    container = ogmrip_plugin_get_subp_codec_by_name (codec);
    g_free (codec);
  }

  return container;
}

/*
 * Common
 */

static void
ogmrip_profile_editor_dialog_combo_get_value (GObject *combo, const gchar *property, GValue *value, gpointer data)
{
  GtkTreeModel *model;
  GtkTreeIter iter;
  gchar *name;

  model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter))
  {
    gtk_tree_model_get (model, &iter, 1, &name, -1);
    g_value_take_string (value, name);
  }
}

/*
 * Container
 */

static void
ogmrip_profile_editor_dialog_container_set_value (GObject *combo, const gchar *property, const GValue *value, const gchar *section)
{
  GType container;
  const gchar *name;

  name = g_value_get_string (value);
  container = ogmrip_gconf_get_container_type (section, name);
  if (container == G_TYPE_NONE)
    gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
  else
    ogmrip_combo_box_set_active_container (GTK_COMBO_BOX (combo), name);
}

static void
ogmrip_profile_editor_dialog_check_container (OGMRipSettings *settings,
    const gchar *section, const gchar *key, const GValue *value, OGMRipProfileEditorDialog *dialog)
{
  GType container;
  const gchar *name = NULL;

  if (value && G_IS_VALUE (value))
    name = g_value_get_string (value);
  container = ogmrip_profile_editor_dialog_get_container_type (dialog, name);

  if (container != G_TYPE_NONE)
  {
    GtkTreeModel *model;
    gchar *codec;

    ogmrip_combo_box_add_video_codecs (GTK_COMBO_BOX (dialog->priv->video_codec_combo), container);
    model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->priv->video_codec_combo));
    gtk_widget_set_sensitive (dialog->priv->video_codec_combo, gtk_tree_model_iter_n_children (model, NULL) > 0);

    ogmrip_settings_get (settings, dialog->priv->profile_section, OGMRIP_GCONF_VIDEO_CODEC, &codec, NULL);
    ogmrip_combo_box_set_active_video_codec (GTK_COMBO_BOX (dialog->priv->video_codec_combo), codec);
    g_free (codec);

    ogmrip_combo_box_add_audio_codecs (GTK_COMBO_BOX (dialog->priv->audio_codec_combo), container);
    model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->priv->audio_codec_combo));
    gtk_widget_set_sensitive (dialog->priv->audio_codec_combo, gtk_tree_model_iter_n_children (model, NULL) > 0);

    ogmrip_settings_get (settings, dialog->priv->profile_section, OGMRIP_GCONF_AUDIO_CODEC, &codec, NULL);
    ogmrip_combo_box_set_active_audio_codec (GTK_COMBO_BOX (dialog->priv->audio_codec_combo), codec);
    g_free (codec);

    ogmrip_combo_box_add_subp_codecs (GTK_COMBO_BOX (dialog->priv->subp_codec_combo), container);
    model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->priv->subp_codec_combo));
    gtk_widget_set_sensitive (dialog->priv->subp_codec_combo, gtk_tree_model_iter_n_children (model, NULL) > 0);

    ogmrip_settings_get (settings, dialog->priv->profile_section, OGMRIP_GCONF_SUBP_CODEC, &codec, NULL);
    ogmrip_combo_box_set_active_subp_codec (GTK_COMBO_BOX (dialog->priv->subp_codec_combo), codec);
    g_free (codec);
  }
}

/*
 * Video Codec
 */

static void
ogmrip_profile_editor_dialog_video_codec_set_value (GObject *combo, const gchar *property, const GValue *value, const gchar *section)
{
  const gchar *name;

  name = g_value_get_string (value);
/*
  if (ogmrip_gconf_get_video_codec_type (section, name) == G_TYPE_NONE)
    gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
  else
*/
    ogmrip_combo_box_set_active_video_codec (GTK_COMBO_BOX (combo), name);
}

static void
ogmrip_profile_editor_dialog_check_video_codec (OGMRipSettings *settings,
    const gchar *section, const gchar *key, const GValue *value, OGMRipProfileEditorDialog *dialog)
{
  GType codec;
  const gchar *name = NULL;
  gint encoding;

  if (value && G_IS_VALUE (value))
    name = g_value_get_string (value);
  codec = ogmrip_profile_editor_dialog_get_video_codec_type (dialog, name);

  if (codec != G_TYPE_NONE)
  {
    gint value;

    value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->priv->passes_spin));
    gtk_spin_button_set_range (GTK_SPIN_BUTTON (dialog->priv->passes_spin), 1.0,
        MIN (100, ogmrip_plugin_get_video_codec_passes (codec)));
    gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->passes_spin), value);
  }

  gtk_widget_set_sensitive (dialog->priv->video_expander, codec != G_TYPE_NONE);

  gtk_widget_set_sensitive (dialog->priv->encoding_label, codec != G_TYPE_NONE);
  gtk_widget_set_sensitive (dialog->priv->encoding_table, codec != G_TYPE_NONE);

  gtk_widget_set_sensitive (dialog->priv->video_preset_label, codec != G_TYPE_NONE);
  gtk_widget_set_sensitive (dialog->priv->video_preset_hbox, codec != G_TYPE_NONE);

  gtk_widget_set_sensitive (dialog->priv->video_options_label, codec != G_TYPE_NONE);
  gtk_widget_set_sensitive (dialog->priv->video_options_vbox, codec != G_TYPE_NONE);

  encoding = gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->priv->encoding_combo));
  gtk_widget_set_sensitive (dialog->priv->passes_label, encoding != QUANTIZER && codec != G_TYPE_NONE);
  gtk_widget_set_sensitive (dialog->priv->passes_hbox, encoding != QUANTIZER && codec != G_TYPE_NONE);
}

/*
 * Audio Codec
 */

static void
ogmrip_profile_editor_dialog_audio_codec_set_value (GObject *combo, const gchar *property, const GValue *value, const gchar *section)
{
  const gchar *name;

  name = g_value_get_string (value);
  if (ogmrip_gconf_get_audio_codec_type (section, name) == G_TYPE_NONE)
    gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
  else
    ogmrip_combo_box_set_active_audio_codec (GTK_COMBO_BOX (combo), name);
}

static void
ogmrip_profile_editor_dialog_check_audio_codec (OGMRipSettings *settings,
    const gchar *section, const gchar *key, const GValue *value, OGMRipProfileEditorDialog *dialog)
{
  GType codec;
  const gchar *name = NULL;
  gint format;

  if (value && G_IS_VALUE (value))
    name = g_value_get_string (value);
  codec = ogmrip_profile_editor_dialog_get_audio_codec_type (dialog, name);

  format = ogmrip_plugin_get_audio_codec_format (codec);

  gtk_widget_set_sensitive (dialog->priv->audio_options_label,
      codec != G_TYPE_NONE && format != OGMRIP_FORMAT_COPY);
  gtk_widget_set_sensitive (dialog->priv->audio_options_table,
      codec != G_TYPE_NONE && format != OGMRIP_FORMAT_COPY);

  gtk_widget_set_sensitive (dialog->priv->audio_quality_label,
      codec != G_TYPE_NONE && format != OGMRIP_FORMAT_COPY &&
      format != OGMRIP_FORMAT_PCM && format != OGMRIP_FORMAT_BPCM && format != OGMRIP_FORMAT_LPCM);
  gtk_widget_set_sensitive (dialog->priv->audio_quality_spin,
      codec != G_TYPE_NONE && format != OGMRIP_FORMAT_COPY &&
      format != OGMRIP_FORMAT_PCM && format != OGMRIP_FORMAT_BPCM && format != OGMRIP_FORMAT_LPCM);
}

/*
 * Subp Codec
 */

static void
ogmrip_profile_editor_dialog_subp_codec_set_value (GObject *combo, const gchar *property, const GValue *value, const gchar *section)
{
  const gchar *name;

  name = g_value_get_string (value);
  if (ogmrip_gconf_get_subp_codec_type (section, name) == G_TYPE_NONE)
    gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
  else
    ogmrip_combo_box_set_active_subp_codec (GTK_COMBO_BOX (combo), name);
}

static void
ogmrip_profile_editor_dialog_check_subp_codec (OGMRipSettings *settings,
    const gchar *section, const gchar *key, const GValue *value, OGMRipProfileEditorDialog *dialog)
{
  GType codec;
  const gchar *name = NULL;

  if (value && G_IS_VALUE (value))
    name = g_value_get_string (value);
  codec = ogmrip_profile_editor_dialog_get_subp_codec_type (dialog, name);

  gtk_widget_set_sensitive (dialog->priv->subp_options_label,
      codec != G_TYPE_NONE && ogmrip_plugin_get_subp_codec_text (codec));
  gtk_widget_set_sensitive (dialog->priv->subp_options_table,
      codec != G_TYPE_NONE && ogmrip_plugin_get_subp_codec_text (codec));
}

/*
 * Scaler
 */

static void
ogmrip_profile_editor_dialog_scaler_combo_get_value (GObject *combo, const gchar *property, GValue *value, gpointer data)
{
  gboolean can_scale = FALSE;
  gint active;

  active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo)) - 1;
  can_scale = active >= 0;

  if (!can_scale)
    ogmrip_settings_get (settings, OGMRIP_PROFILE_EDITOR_DIALOG (data)->priv->profile_section,
        OGMRIP_GCONF_VIDEO_SCALER, &active, NULL);

  g_value_set_int (value, active);

  gtk_widget_set_sensitive (OGMRIP_PROFILE_EDITOR_DIALOG (data)->priv->scale_box, can_scale);
  ogmrip_settings_set (settings, OGMRIP_PROFILE_EDITOR_DIALOG (data)->priv->profile_section,
      OGMRIP_GCONF_VIDEO_CAN_SCALE, can_scale, NULL);
}

static void
ogmrip_profile_editor_dialog_scaler_combo_set_value (GObject *combo, const gchar *property, const GValue *value, gpointer data)
{
  gint active = 0;
  gboolean can_scale;

  ogmrip_settings_get (settings, OGMRIP_PROFILE_EDITOR_DIALOG (data)->priv->profile_section,
      OGMRIP_GCONF_VIDEO_CAN_SCALE, &can_scale, NULL);

  if (can_scale)
  {

    active = g_value_get_int (value);
    active = CLAMP (active, OGMRIP_SCALER_FAST_BILINEAR, OGMRIP_SCALER_BICUBIC_SPLINE) + 1;
  }

  gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
}

/*
 * Max size spin
 */

static void
ogmrip_profile_editor_dialog_max_width_spin_get_value (GObject *spin, const gchar *property, GValue *value, gpointer data)
{
  gint width, height;

  width = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin));
  g_value_set_int (value, width);

  ogmrip_settings_get (settings, OGMRIP_PROFILE_EDITOR_DIALOG (data)->priv->profile_section,
      OGMRIP_GCONF_VIDEO_MAX_HEIGHT, &height, NULL);

  gtk_widget_set_sensitive (OGMRIP_PROFILE_EDITOR_DIALOG (data)->priv->expand_check, width > 0 && height > 0);
}

static void
ogmrip_profile_editor_dialog_max_width_spin_set_value (GObject *spin, const gchar *property, const GValue *value, gpointer data)
{
  gint width, height;

  width = g_value_get_int (value);
  gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), width);

  ogmrip_settings_get (settings, OGMRIP_PROFILE_EDITOR_DIALOG (data)->priv->profile_section,
      OGMRIP_GCONF_VIDEO_MAX_HEIGHT, &height, NULL);

  gtk_widget_set_sensitive (OGMRIP_PROFILE_EDITOR_DIALOG (data)->priv->expand_check, width > 0 && height > 0);
}

static void
ogmrip_profile_editor_dialog_max_height_spin_get_value (GObject *spin, const gchar *property, GValue *value, gpointer data)
{
  gint width, height;

  height = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin));
  g_value_set_int (value, height);

  ogmrip_settings_get (settings, OGMRIP_PROFILE_EDITOR_DIALOG (data)->priv->profile_section,
      OGMRIP_GCONF_VIDEO_MAX_WIDTH, &width, NULL);

  gtk_widget_set_sensitive (OGMRIP_PROFILE_EDITOR_DIALOG (data)->priv->expand_check, width > 0 && height > 0);
}

static void
ogmrip_profile_editor_dialog_max_height_spin_set_value (GObject *spin, const gchar *property, const GValue *value, gpointer data)
{
  gint width, height;

  height = g_value_get_int (value);
  gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), height);

  ogmrip_settings_get (settings, OGMRIP_PROFILE_EDITOR_DIALOG (data)->priv->profile_section,
      OGMRIP_GCONF_VIDEO_MAX_WIDTH, &width, NULL);

  gtk_widget_set_sensitive (OGMRIP_PROFILE_EDITOR_DIALOG (data)->priv->expand_check, width > 0 && height > 0);
}

/*
 * Dialog
 */

G_DEFINE_TYPE (OGMRipProfileEditorDialog, ogmrip_profile_editor_dialog, GTK_TYPE_DIALOG)

static void
ogmrip_profile_editor_dialog_reset_profile_clicked (OGMRipProfileEditorDialog *dialog)
{
  if (dialog->priv->profile_section)
  {
    ogmrip_profiles_reload (ogmrip_get_system_profiles_dir (), dialog->priv->profile_section, NULL);
    ogmrip_profiles_reload (ogmrip_get_user_profiles_dir (), dialog->priv->profile_section, NULL);
  }
}

static void
ogmrip_profile_editor_dialog_container_options_button_clicked (OGMRipProfileEditorDialog *dialog)
{
  GtkWidget *plugin_dialog;
  GType container;

  container = ogmrip_profile_editor_dialog_get_container_type (dialog, NULL);
  plugin_dialog = ogmrip_container_options_plugin_dialog_new (container, dialog->priv->profile_section);
  if (plugin_dialog)
  {
    gtk_window_set_parent (GTK_WINDOW (plugin_dialog), GTK_WINDOW (dialog));
    g_signal_connect (plugin_dialog, "delete-event", G_CALLBACK (gtk_true), NULL);
    g_signal_connect (plugin_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
    gtk_window_present (GTK_WINDOW (plugin_dialog));
  }
}

static void
ogmrip_profile_editor_dialog_video_options_button_clicked (OGMRipProfileEditorDialog *dialog)
{
  GtkWidget *plugin_dialog;
  GType codec;

  codec = ogmrip_profile_editor_dialog_get_video_codec_type  (dialog, NULL);
  plugin_dialog = ogmrip_video_options_plugin_dialog_new (codec, dialog->priv->profile_section);
  if (plugin_dialog)
  {
    gtk_window_set_parent (GTK_WINDOW (plugin_dialog), GTK_WINDOW (dialog));
    g_signal_connect (plugin_dialog, "delete-event", G_CALLBACK (gtk_true), NULL);
    g_signal_connect (plugin_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
    gtk_window_present (GTK_WINDOW (plugin_dialog));
  }
}

static void
ogmrip_profile_editor_dialog_video_encoding_combo_changed (OGMRipProfileEditorDialog *dialog, GtkWidget *combo)
{
  GType codec;
  gint active;

  active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));

  gtk_widget_set_sensitive (dialog->priv->target_label, active == SIZE);
  gtk_widget_set_sensitive (dialog->priv->target_hbox, active == SIZE);

  gtk_widget_set_sensitive (dialog->priv->bitrate_label, active == BITRATE);
  gtk_widget_set_sensitive (dialog->priv->bitrate_hbox, active == BITRATE);

  gtk_widget_set_sensitive (dialog->priv->quantizer_label, active == QUANTIZER);
  gtk_widget_set_sensitive (dialog->priv->quantizer_spin, active == QUANTIZER);

  codec = ogmrip_gconf_get_video_codec_type (dialog->priv->profile_section, NULL);
  gtk_widget_set_sensitive (dialog->priv->passes_label, active != QUANTIZER && codec != G_TYPE_NONE);
  gtk_widget_set_sensitive (dialog->priv->passes_hbox, active != QUANTIZER && codec != G_TYPE_NONE);

  if (active == QUANTIZER)
    gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->passes_spin), 1);
}

static void
ogmrip_profile_editor_dialog_video_preset_combo_changed (OGMRipProfileEditorDialog *dialog, GtkWidget *combo)
{
  if (dialog->priv->video_options_button)
    gtk_widget_set_sensitive (dialog->priv->video_options_button,
        gtk_combo_box_get_active (GTK_COMBO_BOX (combo)) == OGMRIP_VIDEO_PRESET_USER);
}

static void
ogmrip_profile_editor_dialog_audio_options_button_clicked (OGMRipProfileEditorDialog *dialog)
{
  GtkWidget *plugin_dialog;
  GType codec;

  codec = ogmrip_profile_editor_dialog_get_audio_codec_type  (dialog, NULL);
  plugin_dialog = ogmrip_audio_options_plugin_dialog_new (codec, dialog->priv->profile_section);
  if (plugin_dialog)
  {
    gtk_window_set_parent (GTK_WINDOW (plugin_dialog), GTK_WINDOW (dialog));
    g_signal_connect (plugin_dialog, "delete-event", G_CALLBACK (gtk_true), NULL);
    g_signal_connect (plugin_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
    gtk_window_present (GTK_WINDOW (plugin_dialog));
  }
}

static void
ogmrip_profile_editor_dialog_container_combo_changed (OGMRipProfileEditorDialog *dialog, GtkWidget *combo)
{
  GtkTreeIter iter;

  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter))
  {
    GType codec;
    GtkTreeModel *model;
    gchar *name;

    model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
    gtk_tree_model_get (model, &iter, 1, &name, -1);

    codec = ogmrip_profile_editor_dialog_get_container_type (dialog, name);
    g_free (name);

    if (dialog->priv->container_options_button)
      gtk_widget_set_sensitive (dialog->priv->container_options_button,
          ogmrip_options_plugin_exists (codec));
  }
}

static void
ogmrip_profile_editor_dialog_video_codec_combo_changed (OGMRipProfileEditorDialog *dialog, GtkWidget *combo)
{
  GType codec;

  codec = ogmrip_combo_box_get_active_video_codec (GTK_COMBO_BOX (combo));
  if (codec != G_TYPE_NONE)
  {
    GtkTreeModel *model;
    GtkTreeIter iter;
    gboolean exists;
    gint active;

    model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->priv->video_preset_combo));

    if (gtk_tree_model_iter_nth_child (model, &iter, NULL, OGMRIP_VIDEO_PRESET_USER))
      gtk_list_store_remove (GTK_LIST_STORE (model), &iter);

    exists = ogmrip_options_plugin_exists (codec);
    if (exists)
    {
      gtk_list_store_append (GTK_LIST_STORE (model), &iter);
      gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, _("User"), -1);
    }

    active = gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->priv->video_preset_combo));
    
    if (active < 0)
    {
      active = exists ? OGMRIP_VIDEO_PRESET_USER : OGMRIP_VIDEO_PRESET_EXTREME;
      gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->priv->video_preset_combo), active);
    }
  }
}

static void
ogmrip_profile_editor_dialog_audio_codec_combo_changed (OGMRipProfileEditorDialog *dialog, GtkWidget *combo)
{
  if (dialog->priv->audio_options_button)
  {
    GType codec;

    codec = ogmrip_combo_box_get_active_audio_codec (GTK_COMBO_BOX (combo));
    if (codec != G_TYPE_NONE)
      gtk_widget_set_sensitive (dialog->priv->audio_options_button,
          ogmrip_options_plugin_exists (codec));
  }
}

static void
ogmrip_profile_editor_dialog_subp_codec_combo_changed (OGMRipProfileEditorDialog *dialog, GtkWidget *combo)
{
  if (dialog->priv->subp_options_button)
  {
    GType codec;

    codec = ogmrip_combo_box_get_active_subp_codec (GTK_COMBO_BOX (combo));
    if (codec != G_TYPE_NONE)
      gtk_widget_set_sensitive (dialog->priv->subp_options_button,
          ogmrip_options_plugin_exists (codec));
  }
}

static void
ogmrip_profile_editor_dialog_subp_options_button_clicked (OGMRipProfileEditorDialog *dialog)
{
  GtkWidget *plugin_dialog;
  GType codec;

  codec = ogmrip_profile_editor_dialog_get_subp_codec_type  (dialog, NULL);
  plugin_dialog = ogmrip_subp_options_plugin_dialog_new (codec, dialog->priv->profile_section);
  if (plugin_dialog)
  {
    gtk_window_set_parent (GTK_WINDOW (plugin_dialog), GTK_WINDOW (dialog));
    g_signal_connect (plugin_dialog, "delete-event", G_CALLBACK (gtk_true), NULL);
    g_signal_connect (plugin_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
    gtk_window_present (GTK_WINDOW (plugin_dialog));
  }
}

static void
ogmrip_profile_editor_dialog_class_init (OGMRipProfileEditorDialogClass *klass)
{
  GObjectClass *gobject_class;

  gobject_class = G_OBJECT_CLASS (klass);
  gobject_class->finalize = ogmrip_profile_editor_dialog_finalize;

  g_type_class_add_private (klass, sizeof (OGMRipProfileEditorDialogPriv));
}

static void
ogmrip_profile_editor_dialog_init (OGMRipProfileEditorDialog *dialog)
{
  GtkWidget *area, *widget;
  GladeXML *xml;

  dialog->priv = OGMRIP_PROFILE_EDITOR_DIALOG_GET_PRIVATE (dialog);

  dialog->priv->profile_section = g_strdup (_profile_section);

  area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));

  widget = gtk_button_new_with_mnemonic (_("_Reset"));
  gtk_container_add (GTK_CONTAINER (area), widget);
  gtk_widget_show (widget);

  g_signal_connect_swapped (widget, "clicked",
      G_CALLBACK (ogmrip_profile_editor_dialog_reset_profile_clicked), dialog);

  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
      GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
      NULL);
  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
#if !GTK_CHECK_VERSION(2,22,0)
  gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
#endif
  gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
  gtk_window_set_icon_from_stock (GTK_WINDOW (dialog), GTK_STOCK_PREFERENCES);

  xml = glade_xml_new (OGMRIP_DATA_DIR G_DIR_SEPARATOR_S OGMRIP_GLADE_FILE, OGMRIP_GLADE_ROOT, NULL);
  if (!xml)
  {
    g_warning ("Could not find " OGMRIP_GLADE_FILE);
    return;
  }

  dialog->priv->container_options_button = glade_xml_get_widget (xml, "container-options-button");
  g_signal_connect_swapped (dialog->priv->container_options_button, "clicked",
      G_CALLBACK (ogmrip_profile_editor_dialog_container_options_button_clicked), dialog);

  dialog->priv->video_options_button = glade_xml_get_widget (xml, "video-options-button");
  g_signal_connect_swapped (dialog->priv->video_options_button, "clicked",
      G_CALLBACK (ogmrip_profile_editor_dialog_video_options_button_clicked), dialog);

  dialog->priv->audio_options_button = glade_xml_get_widget (xml, "audio-options-button");
  g_signal_connect_swapped (dialog->priv->audio_options_button, "clicked",
      G_CALLBACK (ogmrip_profile_editor_dialog_audio_options_button_clicked), dialog);

  dialog->priv->subp_options_button = glade_xml_get_widget (xml, "subp-options-button");
  g_signal_connect_swapped (dialog->priv->subp_options_button, "clicked",
      G_CALLBACK (ogmrip_profile_editor_dialog_subp_options_button_clicked), dialog);

  area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));

  if (dialog->priv->root)
    gtk_container_remove (GTK_CONTAINER (area), dialog->priv->root);

  dialog->priv->root = glade_xml_get_widget (xml, OGMRIP_GLADE_ROOT);
  gtk_container_add (GTK_CONTAINER (area), dialog->priv->root);
  gtk_widget_show (dialog->priv->root);

  /*
   * Container
   */

  widget = glade_xml_get_widget (xml, "container-combo");
  g_signal_connect_swapped (widget, "changed",
      G_CALLBACK (ogmrip_profile_editor_dialog_container_combo_changed), dialog);

  ogmrip_combo_box_containers_construct (GTK_COMBO_BOX (widget));
  ogmrip_combo_box_add_containers (GTK_COMBO_BOX (widget));
  ogmrip_settings_bind_custom (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_CONTAINER_FORMAT, G_OBJECT (widget), "active",
      ogmrip_profile_editor_dialog_combo_get_value,
      (OGMRipSetFunc) ogmrip_profile_editor_dialog_container_set_value,
      dialog->priv->profile_section);

  dialog->priv->encoding_combo = glade_xml_get_widget (xml, "encoding-combo");
  g_signal_connect_swapped (dialog->priv->encoding_combo, "changed",
      G_CALLBACK (ogmrip_profile_editor_dialog_video_encoding_combo_changed), dialog);

  dialog->priv->target_label = glade_xml_get_widget (xml, "target-label");
  dialog->priv->target_hbox = glade_xml_get_widget (xml, "target-hbox");

  widget = glade_xml_get_widget (xml, "tnumber-spin");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_CONTAINER_TNUMBER, G_OBJECT (widget), "value");

  widget = glade_xml_get_widget (xml, "tsize-spin");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_CONTAINER_TSIZE, G_OBJECT (widget), "value");

  dialog->priv->bitrate_label = glade_xml_get_widget (xml, "bitrate-label");
  dialog->priv->bitrate_hbox = glade_xml_get_widget (xml, "bitrate-hbox");

  widget = glade_xml_get_widget (xml, "bitrate-spin");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_BITRATE, G_OBJECT (widget), "value");

  dialog->priv->quantizer_label = glade_xml_get_widget (xml, "quantizer-label");

  dialog->priv->quantizer_spin = glade_xml_get_widget (xml, "quantizer-spin");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_QUANTIZER, G_OBJECT (dialog->priv->quantizer_spin), "value");

  widget = glade_xml_get_widget (xml, "fourcc-combo");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_CONTAINER_FOURCC, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "ensure-sync-check");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_CONTAINER_ENSURE_SYNC, G_OBJECT (widget), "active");

  /*
   * Video
   */

  dialog->priv->video_codec_combo = glade_xml_get_widget (xml, "video-codec-combo");
  g_signal_connect_swapped (dialog->priv->video_codec_combo, "changed",
      G_CALLBACK (ogmrip_profile_editor_dialog_video_codec_combo_changed), dialog);

  ogmrip_combo_box_video_codecs_construct (GTK_COMBO_BOX (dialog->priv->video_codec_combo));
  ogmrip_settings_bind_custom (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_CODEC, G_OBJECT (dialog->priv->video_codec_combo), "active",
      ogmrip_profile_editor_dialog_combo_get_value,
      (OGMRipSetFunc) ogmrip_profile_editor_dialog_video_codec_set_value,
      dialog->priv->profile_section);

  dialog->priv->video_preset_combo = glade_xml_get_widget (xml, "preset-combo");
  g_signal_connect_swapped (dialog->priv->video_preset_combo, "changed",
      G_CALLBACK (ogmrip_profile_editor_dialog_video_preset_combo_changed), dialog);

  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_PRESET, G_OBJECT (dialog->priv->video_preset_combo), "active");

  dialog->priv->passes_spin = glade_xml_get_widget (xml, "passes-spin");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_PASSES, G_OBJECT (dialog->priv->passes_spin), "value");

  dialog->priv->passes_label = glade_xml_get_widget (xml, "passes-label");
  dialog->priv->passes_hbox = glade_xml_get_widget (xml, "passes-hbox");

  widget = glade_xml_get_widget (xml, "trellis-check");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_TRELLIS, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "qpel-check");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_QPEL, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "turbo-check");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_TURBO, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "denoise-check");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_DENOISE, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "deblock-check");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_DEBLOCK, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "dering-check");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_DERING, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "can-crop-check");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_CAN_CROP, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "scaler-combo");
  ogmrip_settings_bind_custom (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_SCALER, G_OBJECT (widget), "active",
      ogmrip_profile_editor_dialog_scaler_combo_get_value,
      ogmrip_profile_editor_dialog_scaler_combo_set_value,
      dialog);

  dialog->priv->expand_check = glade_xml_get_widget (xml, "expand-check");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_EXPAND, G_OBJECT (dialog->priv->expand_check), "active");

  widget = glade_xml_get_widget (xml, "max-width-spin");
  ogmrip_settings_bind_custom (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_MAX_WIDTH, G_OBJECT (widget), "value",
      ogmrip_profile_editor_dialog_max_width_spin_get_value,
      ogmrip_profile_editor_dialog_max_width_spin_set_value,
      dialog);

  widget = glade_xml_get_widget (xml, "max-height-spin");
  ogmrip_settings_bind_custom (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_MAX_HEIGHT, G_OBJECT (widget), "value",
      ogmrip_profile_editor_dialog_max_height_spin_get_value,
      ogmrip_profile_editor_dialog_max_height_spin_set_value,
      dialog);

  widget = glade_xml_get_widget (xml, "min-width-spin");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_MIN_WIDTH, G_OBJECT (widget), "value");

  widget = glade_xml_get_widget (xml, "min-height-spin");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_MIN_HEIGHT, G_OBJECT (widget), "value");

  /*
   * Audio
   */

  dialog->priv->audio_codec_combo = glade_xml_get_widget (xml, "audio-codec-combo");
  g_signal_connect_swapped (dialog->priv->audio_codec_combo, "changed",
      G_CALLBACK (ogmrip_profile_editor_dialog_audio_codec_combo_changed), dialog);

  ogmrip_combo_box_audio_codecs_construct (GTK_COMBO_BOX (dialog->priv->audio_codec_combo));
  ogmrip_settings_bind_custom (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_AUDIO_CODEC, G_OBJECT (dialog->priv->audio_codec_combo), "active",
      ogmrip_profile_editor_dialog_combo_get_value,
      (OGMRipSetFunc) ogmrip_profile_editor_dialog_audio_codec_set_value,
      dialog->priv->profile_section);

  dialog->priv->audio_quality_label = glade_xml_get_widget (xml, "audio-quality-label");
  dialog->priv->audio_quality_spin = glade_xml_get_widget (xml, "audio-quality-spin");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_AUDIO_QUALITY, G_OBJECT (dialog->priv->audio_quality_spin), "value");

  widget = glade_xml_get_widget (xml, "normalize-check");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_AUDIO_NORMALIZE, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "srate-combo");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_AUDIO_SRATE, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "channels-combo");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_AUDIO_CHANNELS, G_OBJECT (widget), "active");

  /*
   * Subp
   */

  dialog->priv->subp_codec_combo = glade_xml_get_widget (xml, "subp-codec-combo");
  g_signal_connect_swapped (dialog->priv->subp_codec_combo, "changed",
      G_CALLBACK (ogmrip_profile_editor_dialog_subp_codec_combo_changed), dialog);

  ogmrip_combo_box_subp_codecs_construct (GTK_COMBO_BOX (dialog->priv->subp_codec_combo));
  ogmrip_settings_bind_custom (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_SUBP_CODEC, G_OBJECT (dialog->priv->subp_codec_combo), "active",
      ogmrip_profile_editor_dialog_combo_get_value,
      (OGMRipSetFunc) ogmrip_profile_editor_dialog_subp_codec_set_value,
      dialog->priv->profile_section);

  widget = glade_xml_get_widget (xml, "spell-check");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_SPELL_CHECK, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "forced-subs-check");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_FORCED_SUBS, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "charset-combo");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_SUBP_CHARSET, G_OBJECT (widget), "active");

  widget = glade_xml_get_widget (xml, "newline-combo");
  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_SUBP_NEWLINE, G_OBJECT (widget), "active");

  /*
   * Others
   */

  dialog->priv->video_options_label = glade_xml_get_widget (xml, "video-options-label");
  dialog->priv->video_options_vbox = glade_xml_get_widget (xml, "video-options-vbox");

  dialog->priv->video_preset_label = glade_xml_get_widget (xml, "video-preset-label");
  dialog->priv->video_preset_hbox = glade_xml_get_widget (xml, "video-preset-hbox");

  dialog->priv->encoding_label = glade_xml_get_widget (xml, "encoding-label");
  dialog->priv->encoding_table = glade_xml_get_widget (xml, "encoding-table");

  dialog->priv->audio_options_label = glade_xml_get_widget (xml, "audio-options-label");
  dialog->priv->audio_options_table = glade_xml_get_widget (xml, "audio-options-table");

  dialog->priv->subp_options_label = glade_xml_get_widget (xml, "subp-options-label");
  dialog->priv->subp_options_table = glade_xml_get_widget (xml, "subp-options-table");

  dialog->priv->scale_box = glade_xml_get_widget (xml, "scale-box");
  dialog->priv->video_expander = glade_xml_get_widget (xml, "video-options-expander");

  widget = glade_xml_get_widget (xml, "spell-check");
#if HAVE_ENCHANT_SUPPORT
  gtk_widget_set_sensitive (widget, TRUE);
#else
  gtk_widget_set_sensitive (widget, FALSE);
#endif

  ogmrip_settings_bind (settings, dialog->priv->profile_section,
      OGMRIP_GCONF_VIDEO_ENCODING, G_OBJECT (dialog->priv->encoding_combo), "active");

  g_object_unref (xml);

  ogmrip_settings_add_notify_while_alive (settings, _profile_section, OGMRIP_GCONF_CONTAINER_FORMAT,
      (OGMRipNotifyFunc) ogmrip_profile_editor_dialog_check_container, dialog, G_OBJECT (dialog));
  ogmrip_profile_editor_dialog_check_container (settings, _profile_section, OGMRIP_GCONF_CONTAINER_FORMAT, NULL, dialog);

  ogmrip_settings_add_notify_while_alive (settings, _profile_section, OGMRIP_GCONF_VIDEO_CODEC,
      (OGMRipNotifyFunc) ogmrip_profile_editor_dialog_check_video_codec, dialog, G_OBJECT (dialog));
  ogmrip_profile_editor_dialog_check_video_codec (settings, _profile_section, OGMRIP_GCONF_VIDEO_CODEC, NULL, dialog);

  ogmrip_settings_add_notify_while_alive (settings, _profile_section, OGMRIP_GCONF_AUDIO_CODEC,
      (OGMRipNotifyFunc) ogmrip_profile_editor_dialog_check_audio_codec, dialog, G_OBJECT (dialog));
  ogmrip_profile_editor_dialog_check_audio_codec (settings, _profile_section, OGMRIP_GCONF_AUDIO_CODEC, NULL, dialog);

  ogmrip_settings_add_notify_while_alive (settings, _profile_section, OGMRIP_GCONF_SUBP_CODEC,
      (OGMRipNotifyFunc) ogmrip_profile_editor_dialog_check_subp_codec, dialog, G_OBJECT (dialog));
  ogmrip_profile_editor_dialog_check_subp_codec (settings, _profile_section, OGMRIP_GCONF_SUBP_CODEC, NULL, dialog);
}

static void
ogmrip_profile_editor_dialog_finalize (GObject *gobject)
{
  OGMRipProfileEditorDialog *dialog;

  dialog = OGMRIP_PROFILE_EDITOR_DIALOG (gobject);

  if (dialog->priv->profile_section)
  {
    g_free (dialog->priv->profile_section);
    dialog->priv->profile_section = NULL;
  }

  (*G_OBJECT_CLASS (ogmrip_profile_editor_dialog_parent_class)->finalize) (gobject);
}

GtkWidget *
ogmrip_profile_editor_dialog_new (const gchar *profile_section)
{
  GtkWidget *dialog;

  _profile_section = profile_section;
  dialog = g_object_new (OGMRIP_TYPE_PROFILE_EDITOR_DIALOG, NULL);
  _profile_section = NULL;

  return dialog;
}

