/*
 * 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-speex.h"


typedef struct
{
  AudioProfileGeneric *generic;

  gdouble  quality_cbr;
  gdouble  quality_vbr;
  gdouble  bitrate_cbr;
  gdouble  bitrate_abr;
  gchar   *mode;
  gdouble  complexity;
  gchar   *vad;
  gchar   *dtx;
}
AudioProfileSpeex;

typedef enum {
  CONSTANT_BITRATE,
  AVERAGE_BITRATE,
  VARIABLE_BITRATE
} BitrateMode;

BasicFormatInfo speex_bfi = {
  PKGDATADIR "/profiles/gnac-profiles-speex.xml",
  NULL,
  PKGDATADIR "/profiles/speex.xml",
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL
};


static void
gnac_profiles_speex_bitrate_on_changed(GtkComboBox *widget);

static void
gnac_profiles_speex_display_vad(BitrateMode bitrate_mode);

static AudioProfileSpeex *
gnac_profiles_speex_audio_profile_new(void);


void
gnac_profiles_speex_on_bitrate_mode_changed(GtkComboBox *widget,
                                            gpointer     user_data)
{
  gnac_profiles_speex_bitrate_on_changed(widget);
  gnac_profiles_speex_generate_pipeline();
}


static const gchar *
gnac_profiles_speex_init(void)
{
  GtkWidget *widget;
  GtkWidget *widget2;

  gnac_profiles_default_init(&speex_bfi);

  gnac_profiles_utils_init_widget(&speex_bfi, "slider-bitrate-cbr",
      "//variable[@id='bitrate']");
  gnac_profiles_utils_init_widget(&speex_bfi, "slider-bitrate-abr",
      "//variable[@id='abr']");
  gnac_profiles_utils_init_widget(&speex_bfi, "slider-quality-cbr",
      "//variable[@id='quality-cbr']");
  gnac_profiles_utils_init_widget(&speex_bfi, "slider-quality-vbr",
      "//variable[@id='quality-vbr']");
  gnac_profiles_utils_init_widget(&speex_bfi, "checkbutton-vbr",
      "//variable[@id='vbr']");
 
  // Complexity
  widget = gnac_profiles_utils_get_widget(&speex_bfi, "hbox-complexity");
  widget2 = gnac_profiles_utils_init_widget(&speex_bfi, "slider-complexity",
      "//variable[@id='complexity']");
  gnac_profiles_utils_add_description_tooltip(&speex_bfi,
      "//variable[@id='complexity']/description",
      widget, widget2, NULL);

  // vad
  widget = gnac_profiles_utils_init_widget(&speex_bfi, "checkbutton-vad",
      "//variable[@id='vad']");
  gnac_profiles_utils_add_description_tooltip(&speex_bfi,
      "//variable[@id='vad']/description", widget, NULL);

  // dtx
  widget = gnac_profiles_utils_init_widget(&speex_bfi, "checkbutton-dtx",
      "//variable[@id='dtx']");
  gnac_profiles_utils_add_description_tooltip(&speex_bfi,
      "//variable[@id='dtx']/description", widget, NULL);

  // mode
  widget = gnac_profiles_utils_init_widget(&speex_bfi, "combo-mode",
      "//variable[@id='mode']");
  widget2 = gnac_profiles_utils_get_widget(&speex_bfi, "hbox-mode");
  gnac_profiles_utils_add_description_tooltip(&speex_bfi,
      "//variable[@id='mode']/description",
      widget, widget2, NULL);
 
  // Bitrate mode
  widget = gnac_profiles_utils_init_widget(&speex_bfi, "combo-bitrate-mode",
      "//variable[@id='bitrate-mode']");
  
  gnac_profiles_speex_bitrate_on_changed(GTK_COMBO_BOX(widget));
  
  gnac_profiles_xml_engine_free_doc_xpath(speex_bfi.doc);
  speex_bfi.doc = NULL;

  return speex_bfi.format_id;
}


static void
gnac_profiles_speex_show_abr_widgets(gboolean show)
{
  GtkWidget *abr_widgets[] = {
    gnac_profiles_utils_get_widget(&speex_bfi, "label-bitrate-abr"),
    gnac_profiles_utils_get_widget(&speex_bfi, "slider-bitrate-abr"),
  };

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


static void
gnac_profiles_speex_show_cbr_widgets(gboolean show)
{
  GtkWidget *cbr_widgets[] = {
    gnac_profiles_utils_get_widget(&speex_bfi, "checkbutton-bitrate-cbr"),
    gnac_profiles_utils_get_widget(&speex_bfi, "slider-bitrate-cbr"),
    gnac_profiles_utils_get_widget(&speex_bfi, "label-quality-cbr"),
    gnac_profiles_utils_get_widget(&speex_bfi, "hbox-quality-cbr"),
  };

  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_speex_show_vbr_widgets(gboolean show)
{
  GtkWidget *vbr_widgets[] = {
    gnac_profiles_utils_get_widget(&speex_bfi, "label-quality-vbr"),
    gnac_profiles_utils_get_widget(&speex_bfi, "hbox-quality-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 void
gnac_profiles_speex_bitrate_on_changed(GtkComboBox *widget)
{
  BitrateMode bitrate_mode = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));

  gnac_profiles_speex_show_abr_widgets(bitrate_mode == AVERAGE_BITRATE);
  gnac_profiles_speex_show_cbr_widgets(bitrate_mode == CONSTANT_BITRATE);
  gnac_profiles_speex_show_vbr_widgets(bitrate_mode == VARIABLE_BITRATE);

  gnac_profiles_speex_display_vad(bitrate_mode);
}


static void
gnac_profiles_speex_display_vad(BitrateMode bitrate_mode)
{
  GtkWidget *vad = gnac_profiles_utils_get_widget(&speex_bfi, "checkbutton-vad");
  GtkWidget *dtx = gnac_profiles_utils_get_widget(&speex_bfi, "checkbutton-dtx");

  if (bitrate_mode == CONSTANT_BITRATE) {
    gtk_widget_show(vad);
    gnac_profiles_speex_vad_on_toggle(GTK_TOGGLE_BUTTON(vad), NULL);
  } else {
    gtk_widget_hide(vad);
    gtk_widget_show(dtx);
  }

  gnac_profiles_utils_set_active_toggle_button(&speex_bfi,
      (bitrate_mode == VARIABLE_BITRATE), "checkbutton-vbr", NULL);
}


void
gnac_profiles_speex_generate_pipeline(void)
{
  gchar *pipeline = gnac_profiles_default_generate_pipeline(&speex_bfi);
  GtkWidget *widget = gnac_profiles_utils_get_widget(&speex_bfi,
      "combo-bitrate-mode");

  BitrateMode bitrate_mode = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));

  switch (bitrate_mode)
  {
    case CONSTANT_BITRATE:
      pipeline = gnac_profiles_utils_add_properties_slider(pipeline,
          &speex_bfi, "%.0f", "slider-quality-cbr", NULL);
      widget = gnac_profiles_utils_get_widget(&speex_bfi,
          "checkbutton-bitrate-cbr");

      if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
        widget = gnac_profiles_utils_get_widget(&speex_bfi,
            "slider-bitrate-cbr");
        pipeline = gnac_profiles_utils_add_property_slider(pipeline,
            "%.0f", 1024, widget);
      }

      pipeline = gnac_profiles_utils_add_properties(pipeline, &speex_bfi,
          "checkbutton-vad", NULL);
      widget = gnac_profiles_utils_get_widget(&speex_bfi, "checkbutton-vad");

      if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
        pipeline = gnac_profiles_utils_add_properties(pipeline,
            &speex_bfi, "checkbutton-dtx", NULL);
      }
      break;

    case AVERAGE_BITRATE:
      widget = gnac_profiles_utils_get_widget(&speex_bfi, "slider-bitrate-abr");
      pipeline = gnac_profiles_utils_add_property_slider(pipeline,
          "%.0f", 1024, widget);
      pipeline = gnac_profiles_utils_add_properties(pipeline, &speex_bfi,
          "checkbutton-dtx", NULL);
      break;

    case VARIABLE_BITRATE:
      pipeline = gnac_profiles_utils_add_properties_slider(pipeline,
          &speex_bfi, "%.2f", "slider-quality-vbr", NULL);
      pipeline = gnac_profiles_utils_add_properties(pipeline, &speex_bfi,
          "checkbutton-vbr", "checkbutton-dtx", NULL);
      break;
  }
  
  pipeline = gnac_profiles_utils_add_properties_checked_slider(pipeline,
      &speex_bfi, "slider-complexity", "checkbutton-complexity", NULL);
  pipeline = gnac_profiles_utils_add_properties(pipeline, &speex_bfi,
      "combo-mode", NULL);
  pipeline = gnac_profiles_utils_add_pipe(pipeline,
      speex_bfi.pipeline_multiplexers);

  gnac_profiles_properties_update_textbuffer(pipeline);

  g_free(speex_bfi.pipeline);

  speex_bfi.pipeline = pipeline;
}


void
gnac_profiles_speex_advanced_on_toggle(GtkWidget       *widget,
                                       GtkToggleButton *togglebutton)
{
  gnac_profiles_utils_on_toggle_optionnal_property(togglebutton, widget);
  gnac_profiles_speex_generate_pipeline();
}


void
gnac_profiles_speex_vad_on_toggle(GtkToggleButton *togglebutton,
                                  gpointer         user_data)
{
  GtkWidget *dtx = gnac_profiles_utils_get_widget(&speex_bfi, "checkbutton-dtx");

  if (gtk_toggle_button_get_active(togglebutton)) {
    gtk_widget_show(dtx);
  } else {
    gtk_widget_hide(dtx);
  }

  gnac_profiles_speex_generate_pipeline();
}


static void
gnac_profiles_speex_reset_ui(void)
{
  gnac_profiles_default_reset_ui(&speex_bfi);
  gnac_profiles_utils_reset_values(&speex_bfi,
      "combo-bitrate-mode", "combo-mode", "slider-quality-cbr",
      "slider-quality-vbr", "slider-bitrate-cbr", "slider-bitrate-abr",
      "slider-complexity", "checkbutton-vad", "checkbutton-dtx", NULL);
  gnac_profiles_utils_set_active_toggle_button(&speex_bfi, FALSE,
      "checkbutton-complexity", "checkbutton-bitrate-cbr", NULL);
}


static void
gnac_profiles_speex_set_fields(gpointer data)
{
  if (!data) {
    gnac_profiles_speex_reset_ui();
    return;
  }

  AudioProfileSpeex *profile = (AudioProfileSpeex *) data;
  gnac_profiles_default_init_fields(profile->generic, &speex_bfi);
  gnac_profiles_utils_set_values_checked(&speex_bfi,
      "slider-complexity", "checkbutton-complexity",
      profile->complexity, NULL);
  gnac_profiles_utils_set_values(&speex_bfi,
      "combo-mode", profile->mode,
      "checkbutton-vad", profile->vad,
      "checkbutton-dtx", profile->dtx, NULL);

  GtkWidget *widget = gnac_profiles_utils_get_widget(&speex_bfi,
      "combo-bitrate-mode");

  if (profile->quality_cbr != -1)
  {
    gnac_profiles_utils_set_values(&speex_bfi,
        "slider-bitrate-cbr", profile->bitrate_cbr, NULL);

    if (profile->bitrate_cbr != 1) {
      gnac_profiles_utils_set_values_checked(&speex_bfi,
          "slider-bitrate-cbr", "checkbutton-bitrate-cbr",
          profile->bitrate_cbr, NULL);
    }

    gtk_combo_box_set_active(GTK_COMBO_BOX(widget), CONSTANT_BITRATE);
  }
  else if (profile->quality_vbr != -1)
  {
    gnac_profiles_utils_set_active_toggle_button(&speex_bfi, TRUE,
        "checkbutton-vbr", NULL);
    gnac_profiles_utils_set_values(&speex_bfi,
        "slider-quality-vbr", profile->quality_vbr, NULL);
    gtk_combo_box_set_active(GTK_COMBO_BOX(widget), VARIABLE_BITRATE);
  }
  else
  {
    gnac_profiles_utils_set_values(&speex_bfi,
        "slider-bitrate-abr", profile->bitrate_abr, NULL);
    gtk_combo_box_set_active(GTK_COMBO_BOX(widget), AVERAGE_BITRATE);
  }
}


static gchar *
gnac_profiles_speex_get_combo_format_name(void)
{
  return gnac_profiles_default_get_combo_format_name(&speex_bfi);
}


static AudioProfileSpeex *
gnac_profiles_speex_audio_profile_new(void)
{
  AudioProfileSpeex *profile = g_malloc(sizeof(AudioProfileSpeex));
  
  profile->quality_cbr = -1;
  profile->quality_vbr = -1;
  profile->bitrate_cbr = -1;
  profile->bitrate_abr = -1;
  profile->mode = NULL;
  profile->complexity =  -1;
  profile->vad = NULL;
  profile->dtx = NULL;

  return profile;
}


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

  AudioProfileSpeex *profile = (AudioProfileSpeex *) data;
  gnac_profiles_utils_free_audio_profile_generic(profile->generic); 
  g_free(profile->mode);
  g_free(profile->vad);
  g_free(profile->dtx);
  g_free(profile);
}


static gpointer
gnac_profiles_speex_generate_audio_profile(GError **error)
{
  AudioProfileGeneric *generic = gnac_profiles_default_generate_audio_profile(
      &speex_bfi);
  AudioProfileSpeex *profile = gnac_profiles_speex_audio_profile_new();
  profile->generic = generic;
  GtkWidget *widget = gnac_profiles_utils_get_widget(&speex_bfi,
      "combo-bitrate-mode");
  BitrateMode bitrate_mode = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));

  gnac_profiles_utils_get_values_and_set(&speex_bfi,
      "combo-mode", &profile->mode,
      "checkbutton-dtx", &profile->dtx, NULL);
  gnac_profiles_utils_get_values_checked_slider_and_set(&speex_bfi, 
      "slider-complexity", "checkbutton-complexity", &profile->complexity, NULL);

  switch (bitrate_mode)
  {
    case CONSTANT_BITRATE:
      gnac_profiles_utils_get_values_and_set(&speex_bfi,
          "slider-quality-cbr", &profile->quality_cbr,
          "checkbutton-vad", &profile->vad, NULL);
      gnac_profiles_utils_get_values_checked_slider_and_set(&speex_bfi, 
          "slider-bitrate-cbr", "checkbutton-bitrate-cbr",
          &profile->bitrate_cbr, NULL);
      break;

    case AVERAGE_BITRATE:
      gnac_profiles_utils_get_values_and_set(&speex_bfi,
          "slider-bitrate-abr", &profile->bitrate_abr, NULL);
      break;

    case VARIABLE_BITRATE:
      gnac_profiles_utils_get_values_and_set(&speex_bfi,
          "slider-quality-vbr", &profile->quality_vbr, NULL);
      break;
  }
  
  return profile;
}


static GtkWidget *
gnac_profiles_speex_get_widget(void)
{
  return gnac_profiles_default_get_properties_alignment(&speex_bfi);
}


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

  gchar *quality_cbr = NULL;
  gchar *bitrate_cbr = NULL;
  gchar *bitrate_abr = NULL;
  gchar *quality_vbr = NULL;
  gchar *complexity = NULL;
  AudioProfileSpeex *profile = (AudioProfileSpeex *) data;
  
  if (profile->quality_cbr != -1)
  {
    quality_cbr = gnac_profiles_utils_gdouble_to_gchararray(
        profile->quality_cbr);

    if (profile->bitrate_cbr != -1) {
      bitrate_cbr = gnac_profiles_utils_gdouble_to_gchararray(
          profile->bitrate_cbr);
    }
  }
  else if (profile->quality_vbr != -1)
  {
    quality_vbr = gnac_profiles_utils_gdouble_to_gchararray_format(
        profile->quality_vbr, "%.2f");
  }
  else
  {
    bitrate_abr = gnac_profiles_utils_gdouble_to_gchararray(
        profile->bitrate_abr);
  }
  
  if (profile->complexity != -1) {
    complexity = gnac_profiles_utils_gdouble_to_gchararray(
        profile->complexity);
  }

  XMLDoc *doc = gnac_profiles_default_save_profile(profile->generic, &speex_bfi);
  gnac_profiles_xml_engine_add_values(doc,
      "bitrate-cbr", bitrate_cbr, "quality-cbr", quality_cbr,
      "bitrate-abr", bitrate_abr, "quality-vbr", quality_vbr,
      "mode", profile->mode, "complexity", complexity,
      "vad", profile->vad, "dtx", profile->dtx, NULL);

  gnac_profiles_xml_engine_save_doc(doc, profile->generic->name);

  gnac_profiles_xml_engine_free_doc_xpath(doc);
  g_free(quality_cbr);
  g_free(quality_vbr);
  g_free(bitrate_cbr);
  g_free(bitrate_abr);
  g_free(complexity);
}


static gpointer
gnac_profiles_speex_load_specific_properties(XMLDoc              *doc,
                                             AudioProfileGeneric *generic)
{
  gchar *quality_cbr;
  gchar *bitrate_cbr;
  gchar *bitrate_abr;
  gchar *quality_vbr;
  gchar *complexity;
  
  AudioProfileSpeex *profile = gnac_profiles_speex_audio_profile_new();
  profile->generic = generic;
  gnac_profiles_utils_load_saved_profile(doc,
      "/audio-profile/format-specific/",
      "bitrate-cbr", &bitrate_cbr, "quality-cbr", &quality_cbr,
      "bitrate-abr", &bitrate_abr, "quality-vbr", &quality_vbr,
      "mode", &profile->mode, "complexity", &complexity,
      "vad", &profile->vad, "dtx", &profile->dtx, NULL);
  
  if (complexity) {
    profile->complexity = gnac_profiles_utils_gchararray_to_gdouble(
        complexity);
    g_free(complexity);
  }

  if (quality_cbr)
  {
    profile->quality_cbr = gnac_profiles_utils_gchararray_to_gdouble(
        quality_cbr);

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

    g_free(quality_cbr);
  }
  else if (quality_vbr)
  {
    profile->quality_vbr = gnac_profiles_utils_gchararray_to_gdouble(
        quality_vbr);
    g_free(quality_vbr);
  }
  else
  {
    profile->bitrate_abr = gnac_profiles_utils_gchararray_to_gdouble(
        bitrate_abr);
    g_free(bitrate_abr);
  }

  return profile;
}


static void
gnac_profiles_speex_clean_up(void)
{
  gnac_profiles_default_clean_up(&speex_bfi);
  gnac_profiles_utils_free_values(&speex_bfi,
      "combo-mode", "combo-bitrate-mode", "slider-quality-cbr",
      "slider-quality-vbr", "slider-bitrate-cbr", "slider-bitrate-abr",
      "slider-complexity", "checkbutton-vad", "checkbutton-dtx",
      "checkbutton-vbr", NULL);
  gnac_profiles_utils_free_basic_format_info(&speex_bfi);
}


static const gchar *
gnac_profiles_speex_get_plugin_name(void)
{
  return speex_bfi.format_plugin_name;
}


static const gchar *
gnac_profiles_speex_get_description(void)
{
  return speex_bfi.description;
}


FormatModuleFuncs
gnac_profiles_speex_get_funcs(void)
{
  FormatModuleFuncs funcs = {
    gnac_profiles_speex_init,
    gnac_profiles_speex_get_description,
    gnac_profiles_speex_generate_pipeline,
    gnac_profiles_speex_generate_audio_profile,
    gnac_profiles_speex_free_audio_profile,
    gnac_profiles_speex_set_fields,
    gnac_profiles_speex_get_widget,
    gnac_profiles_speex_save_profile,
    gnac_profiles_speex_load_specific_properties,
    gnac_profiles_speex_clean_up,
    NULL,
    gnac_profiles_speex_get_combo_format_name,
    gnac_profiles_speex_get_plugin_name
  };

  return funcs;
}
