/*
 * 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
 */

#include <glib/gstdio.h>

#include "../gnac-profiles-properties.h"
#include "gnac-profiles-vorbis.h"


typedef struct
{
  AudioProfileGeneric *generic;

  gdouble  quality;
  gchar   *bitrate;
  gchar   *min_bitrate;
  gchar   *max_bitrate;
}
AudioProfileVorbis;

typedef enum {
  VARIABLE_BITRATE,
  CONSTANT_BITRATE
} EncodingMode;

BasicFormatInfo vorbis_bfi = {
  PKGDATADIR "/profiles/gnac-profiles-vorbis.xml",
  NULL,
  PKGDATADIR "/profiles/vorbis.xml",
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL
};


static void
gnac_profiles_vorbis_vbr_on_changed(GtkComboBox *widget);

static AudioProfileVorbis *
gnac_profiles_vorbis_audio_profile_new(void);


void
gnac_profiles_vorbis_on_encoding_mode_changed(GtkComboBox *widget,
                                              gpointer     user_data)
{
  gnac_profiles_vorbis_vbr_on_changed(widget);
  gnac_profiles_vorbis_generate_pipeline();
}


static void
gnac_profiles_vorbis_show_cbr_widgets(gboolean show)
{
  GtkWidget *cbr_widgets[] = {
    gnac_profiles_utils_get_widget(&vorbis_bfi, "label-bitrate"),
    gnac_profiles_utils_get_widget(&vorbis_bfi, "hbox-bitrate"),
  };

  guint i;
  for (i = 0; i < G_N_ELEMENTS(cbr_widgets); i++) {
    if (show) gtk_widget_show_all(cbr_widgets[i]);
    else gtk_widget_hide(cbr_widgets[i]);
  }
}


static void
gnac_profiles_vorbis_show_vbr_widgets(gboolean show)
{
  GtkWidget *vbr_widgets[] = {
    gnac_profiles_utils_get_widget(&vorbis_bfi, "label-quality"),
    gnac_profiles_utils_get_widget(&vorbis_bfi, "hbox-quality"),
    gnac_profiles_utils_get_widget(&vorbis_bfi, "checkbutton-min-bitrate"),
    gnac_profiles_utils_get_widget(&vorbis_bfi, "checkbutton-max-bitrate"),
    gnac_profiles_utils_get_widget(&vorbis_bfi, "combo-max-vbr"),
    gnac_profiles_utils_get_widget(&vorbis_bfi, "combo-min-vbr")
  };

  guint i;
  for (i = 0; i < G_N_ELEMENTS(vbr_widgets); i++) {
    if (show) gtk_widget_show_all(vbr_widgets[i]);
    else gtk_widget_hide(vbr_widgets[i]);
  }
}


static const gchar *
gnac_profiles_vorbis_init(void)
{
  GtkWidget *widget;

  gnac_profiles_default_init(&vorbis_bfi);

  // Bitrate
  gnac_profiles_utils_init_widget(&vorbis_bfi, "combo-bitrate",
      "//variable[@id='bitrate']");
  
  // Quality
  gnac_profiles_utils_init_widget(&vorbis_bfi, "slider-quality",
      "//variable[@id='quality']");
 
  // Min bitrate
  gnac_profiles_utils_init_widget(&vorbis_bfi, "combo-min-vbr",
      "//variable[@id='vbr-min-bitrate']");
  
  // Max bitrate
  gnac_profiles_utils_init_widget(&vorbis_bfi, "combo-max-vbr",
      "//variable[@id='vbr-max-bitrate']");

  // Encoding mode
  widget = gnac_profiles_utils_init_widget(&vorbis_bfi, "combo-encoding-mode",
      "//variable[@id='vbr']");
  
  gnac_profiles_vorbis_vbr_on_changed(GTK_COMBO_BOX(widget));
  
  gnac_profiles_xml_engine_free_doc_xpath(vorbis_bfi.doc);
  vorbis_bfi.doc = NULL;

  return vorbis_bfi.format_id;
}


static void
gnac_profiles_vorbis_vbr_on_changed(GtkComboBox *widget)
{
  EncodingMode encoding_mode = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));

  gnac_profiles_vorbis_show_cbr_widgets(encoding_mode == CONSTANT_BITRATE);
  gnac_profiles_vorbis_show_vbr_widgets(encoding_mode == VARIABLE_BITRATE);
}


void
gnac_profiles_vorbis_generate_pipeline(void)
{
  gchar *pipeline = gnac_profiles_default_generate_pipeline(&vorbis_bfi);
  GtkWidget *widget = gnac_profiles_utils_get_widget(&vorbis_bfi,
      "combo-encoding-mode");
  EncodingMode encoding_mode = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));

  if (encoding_mode == CONSTANT_BITRATE) {
    pipeline = gnac_profiles_utils_add_properties(pipeline,
        &vorbis_bfi, "combo-bitrate", NULL);
  } else if (encoding_mode == VARIABLE_BITRATE) {
    pipeline = gnac_profiles_utils_add_properties_slider(pipeline,
        &vorbis_bfi, "%.1f", "slider-quality", NULL);
    pipeline = gnac_profiles_utils_add_properties_checked_combo(pipeline,
        &vorbis_bfi,
        "combo-min-vbr", "checkbutton-min-bitrate",
        "combo-max-vbr", "checkbutton-max-bitrate",
        NULL);
  }

  pipeline = gnac_profiles_utils_add_pipe(pipeline,
      vorbis_bfi.pipeline_multiplexers);
  gnac_profiles_properties_update_textbuffer(pipeline);

  g_free(vorbis_bfi.pipeline);

  vorbis_bfi.pipeline = pipeline;
}


void
gnac_profiles_vorbis_advanced_bitrate_on_toggle(GtkWidget       *widget,
                                                GtkToggleButton *togglebutton)
{
  gnac_profiles_utils_on_toggle_optionnal_property(togglebutton, widget);
  gnac_profiles_vorbis_generate_pipeline();
}


static void
gnac_profiles_vorbis_reset_ui(void)
{
  gnac_profiles_default_reset_ui(&vorbis_bfi);
  gnac_profiles_utils_reset_values(&vorbis_bfi,
      "combo-encoding-mode", "combo-bitrate", "combo-min-vbr",
      "combo-max-vbr", "slider-quality", NULL);
  gnac_profiles_utils_set_active_toggle_button(&vorbis_bfi, FALSE,
      "checkbutton-min-bitrate", "checkbutton-max-bitrate", NULL);
}


static void
gnac_profiles_vorbis_set_fields(gpointer data)
{
  if (!data) {
    gnac_profiles_vorbis_reset_ui();
    return;
  }

  AudioProfileVorbis *profile = (AudioProfileVorbis *) data;
  GtkWidget *widget = gnac_profiles_utils_get_widget(&vorbis_bfi,
      "combo-encoding-mode");
  gnac_profiles_default_init_fields(profile->generic, &vorbis_bfi);

  if (profile->quality == -1) {
    gnac_profiles_utils_set_values(&vorbis_bfi,
        "combo-bitrate", profile->bitrate, NULL);
    gtk_combo_box_set_active(GTK_COMBO_BOX(widget), CONSTANT_BITRATE);
  } else {
    gnac_profiles_utils_set_values(&vorbis_bfi,
        "slider-quality", profile->quality, NULL);
    gnac_profiles_utils_set_values_checked(&vorbis_bfi,
        "combo-min-vbr", "checkbutton-min-bitrate", profile->min_bitrate,
        "combo-max-vbr", "checkbutton-max-bitrate", profile->max_bitrate,
        NULL);
    gtk_combo_box_set_active(GTK_COMBO_BOX(widget), VARIABLE_BITRATE);
  }
}


static gchar *
gnac_profiles_vorbis_get_combo_format_name(void)
{
  return gnac_profiles_default_get_combo_format_name(&vorbis_bfi);
}


static AudioProfileVorbis *
gnac_profiles_vorbis_audio_profile_new(void)
{
  AudioProfileVorbis *profile = g_malloc(sizeof(AudioProfileVorbis));
  
  profile->quality = -1;
  profile->bitrate = NULL;
  profile->min_bitrate = NULL;
  profile->max_bitrate = NULL;

  return profile;
}


static void
gnac_profiles_vorbis_free_audio_profile(gpointer data)
{
  if (!data) return;

  AudioProfileVorbis *profile = (AudioProfileVorbis *) data;
  gnac_profiles_utils_free_audio_profile_generic(profile->generic); 
  g_free(profile->bitrate);
  g_free(profile->min_bitrate);
  g_free(profile->max_bitrate);
  g_free(profile);
}


static gpointer
gnac_profiles_vorbis_generate_audio_profile(GError **error)
{
  AudioProfileGeneric *generic = gnac_profiles_default_generate_audio_profile(
      &vorbis_bfi);
  AudioProfileVorbis *profile = gnac_profiles_vorbis_audio_profile_new();
  profile->generic = generic;
  GtkWidget *widget = gnac_profiles_utils_get_widget(&vorbis_bfi,
      "combo-encoding-mode");
  EncodingMode encoding_mode = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));

  if (encoding_mode == CONSTANT_BITRATE) {
    gnac_profiles_utils_get_values_and_set(&vorbis_bfi,
        "combo-bitrate", &profile->bitrate, NULL);
  } else {
    gnac_profiles_utils_get_values_and_set(&vorbis_bfi,
        "slider-quality", &profile->quality, NULL);
    gnac_profiles_utils_get_values_checked_combo_and_set(&vorbis_bfi, 
        "combo-min-vbr", "checkbutton-min-bitrate", &profile->min_bitrate,
        "combo-max-vbr", "checkbutton-max-bitrate", &profile->max_bitrate,
        NULL);
  }
  
  return profile;
}


static GtkWidget *
gnac_profiles_vorbis_get_widget(void)
{
  return gnac_profiles_default_get_properties_alignment(&vorbis_bfi);
}


static void
gnac_profiles_vorbis_save_profile(gpointer data)
{
  if (!data) return;

  AudioProfileVorbis *profile = (AudioProfileVorbis *) data;
  gchar *quality = gnac_profiles_utils_gdouble_to_gchararray_format(
      profile->quality, "%.1f");
  XMLDoc *doc = gnac_profiles_default_save_profile(profile->generic, &vorbis_bfi);
  gnac_profiles_xml_engine_add_values(doc,
      "quality", quality, "bitrate", profile->bitrate,
      "min-bitrate", profile->min_bitrate,
      "max-bitrate", profile->max_bitrate, NULL);

  gnac_profiles_xml_engine_save_doc(doc, profile->generic->name);
  gnac_profiles_xml_engine_free_doc_xpath(doc);
  g_free(quality);
}


static gpointer
gnac_profiles_vorbis_load_specific_properties(XMLDoc              *doc,
                                              AudioProfileGeneric *generic)
{
  gchar *quality;
  
  AudioProfileVorbis *profile = gnac_profiles_vorbis_audio_profile_new();
  profile->generic = generic;
  gnac_profiles_utils_load_saved_profile(doc,
      "/audio-profile/format-specific/",
      "quality", &quality,
      "bitrate", &profile->bitrate,
      "min-bitrate", &profile->min_bitrate,
      "max-bitrate", &profile->max_bitrate,
      NULL);

  if (quality) {
    profile->quality = gnac_profiles_utils_gchararray_to_gdouble(quality);
    g_free(quality);
  }

  return profile;
}


static void
gnac_profiles_vorbis_clean_up(void)
{
  gnac_profiles_default_clean_up(&vorbis_bfi);
  gnac_profiles_utils_free_values(&vorbis_bfi,
      "combo-bitrate", "combo-min-vbr", "combo-max-vbr",
      "combo-encoding-mode", "slider-quality", NULL);
  gnac_profiles_utils_free_basic_format_info(&vorbis_bfi);
}


static const gchar *
gnac_profiles_vorbis_get_plugin_name(void)
{
  return vorbis_bfi.format_plugin_name;
}


static const gchar *
gnac_profiles_vorbis_get_description(void)
{
  return vorbis_bfi.description;
}


FormatModuleFuncs
gnac_profiles_vorbis_get_funcs(void)
{
  FormatModuleFuncs funcs = {
    gnac_profiles_vorbis_init,
    gnac_profiles_vorbis_get_description,
    gnac_profiles_vorbis_generate_pipeline,
    gnac_profiles_vorbis_generate_audio_profile,
    gnac_profiles_vorbis_free_audio_profile,
    gnac_profiles_vorbis_set_fields,
    gnac_profiles_vorbis_get_widget,
    gnac_profiles_vorbis_save_profile,
    gnac_profiles_vorbis_load_specific_properties,
    gnac_profiles_vorbis_clean_up,
    NULL,
    gnac_profiles_vorbis_get_combo_format_name,
    gnac_profiles_vorbis_get_plugin_name
  };

  return funcs;
}
