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


typedef struct
{
  AudioProfileGeneric *generic;

  gchar   *mode;
  gdouble  bitrate;
  gdouble  bits_per_sample;
  gdouble  extra_processing;
  gchar   *joint_stereo_mode;
  gchar   *md5;
}
AudioProfileWavpack;

typedef enum {
  AVERAGE_BITRATE,
  BITS_PER_SAMPLE
} ControlMethod;

BasicFormatInfo wavpack_bfi = {
  PKGDATADIR "/profiles/gnac-profiles-wavpack.xml",
  NULL,
  PKGDATADIR "/profiles/wavpack.xml",
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL
};


static void
gnac_profiles_wavpack_bitrate_control_on_changed(GtkComboBox *widget);

static AudioProfileWavpack *
gnac_profiles_wavpack_audio_profile_new(void);


void
gnac_profiles_wavpack_on_bitrate_control_changed(GtkComboBox *widget,
                                                 gpointer     user_data)
{
  gnac_profiles_wavpack_bitrate_control_on_changed(widget);
  gnac_profiles_wavpack_generate_pipeline();
}


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

  gnac_profiles_default_init(&wavpack_bfi);

  // Encoding mode
  gnac_profiles_utils_init_widget(&wavpack_bfi, "combo-mode",
      "//variable[@id='mode']");

  // Bitrate
  gnac_profiles_utils_init_widget(&wavpack_bfi, "slider-bitrate",
      "//variable[@id='bitrate']");

  // Bits per sample
  gnac_profiles_utils_init_widget(&wavpack_bfi, "slider-bits-per-sample",
      "//variable[@id='bits-per-sample']");
 
  // Extra processing
  widget = gnac_profiles_utils_init_widget(&wavpack_bfi,
      "slider-extra-processing", "//variable[@id='extra-processing']");
  widget2 = gnac_profiles_utils_get_widget(&wavpack_bfi,
      "label-extra-processing"),
  gnac_profiles_utils_add_description_tooltip(&wavpack_bfi,
      "//variable[@id='extra-processing']/description",
      widget, widget2, NULL);

  // Joint stereo mode
  gnac_profiles_utils_init_widget(&wavpack_bfi,
      "combo-joint-stereo-mode", "//variable[@id='joint-stereo-mode']");

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

 // Bitrate control
  widget = gnac_profiles_utils_init_widget(&wavpack_bfi,
      "combo-bitrate-control", "//variable[@id='bitrate-control']");
  widget2 = gnac_profiles_utils_get_widget(&wavpack_bfi,
      "checkbutton-bitrate-control");
  gnac_profiles_wavpack_bitrate_control_on_toggle(widget,
      GTK_TOGGLE_BUTTON(widget2));

  gnac_profiles_xml_engine_free_doc_xpath(wavpack_bfi.doc);
  wavpack_bfi.doc = NULL;

  return wavpack_bfi.format_id;
}


static void
gnac_profiles_wavpack_show_abr_widgets(gboolean show)
{
  GtkWidget *abr_widgets[] = {
    gnac_profiles_utils_get_widget(&wavpack_bfi, "label-bitrate"),
    gnac_profiles_utils_get_widget(&wavpack_bfi, "slider-bitrate"),
    gnac_profiles_utils_get_widget(&wavpack_bfi, "label-bits-per-sample"),
    gnac_profiles_utils_get_widget(&wavpack_bfi, "slider-bits-per-sample"),
  };

  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_wavpack_show_bps_widgets(gboolean show)
{
  GtkWidget *bps_widgets[] = {
    gnac_profiles_utils_get_widget(&wavpack_bfi, "label-bits-per-sample"),
    gnac_profiles_utils_get_widget(&wavpack_bfi, "slider-bits-per-sample"),
  };

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


static void
gnac_profiles_wavpack_bitrate_control_on_changed(GtkComboBox *widget)
{
  GtkToggleButton *bitrate_ctrl_btn = GTK_TOGGLE_BUTTON(
      gnac_profiles_utils_get_widget(&wavpack_bfi, "checkbutton-bitrate-control"));
  gboolean bitrate_ctrl_enabled = gtk_toggle_button_get_active(bitrate_ctrl_btn);
  ControlMethod control_method = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
  
  gnac_profiles_wavpack_show_abr_widgets(
      bitrate_ctrl_enabled && control_method == AVERAGE_BITRATE);
  gnac_profiles_wavpack_show_bps_widgets(
      bitrate_ctrl_enabled && control_method == BITS_PER_SAMPLE);
}


void
gnac_profiles_wavpack_generate_pipeline(void)
{
  gchar *pipeline = gnac_profiles_default_generate_pipeline(&wavpack_bfi);
  GtkWidget *widget = gnac_profiles_utils_get_widget(&wavpack_bfi,
      "combo-bitrate-control");

  pipeline = gnac_profiles_utils_add_properties(pipeline, &wavpack_bfi,
      "combo-mode",  NULL);
  pipeline = gnac_profiles_utils_add_properties_slider(pipeline, &wavpack_bfi, 
      "%.0f", "slider-extra-processing", NULL);
  pipeline = gnac_profiles_utils_add_properties_checked_combo(pipeline,
      &wavpack_bfi,
      "combo-joint-stereo-mode", "checkbutton-joint-stereo-mode",
      NULL);
  pipeline = gnac_profiles_utils_add_properties(pipeline, &wavpack_bfi,
      "checkbutton-md5", NULL);
  GtkWidget *check = gnac_profiles_utils_get_widget(&wavpack_bfi,
      "checkbutton-bitrate-control");

  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) {
    ControlMethod control_method = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));

    if (control_method == AVERAGE_BITRATE) {
      widget = gnac_profiles_utils_get_widget(&wavpack_bfi, "slider-bitrate");
      pipeline = gnac_profiles_utils_add_property_slider(pipeline,
          "%.0f", 1000, widget);
    } else {
      pipeline = gnac_profiles_utils_add_properties_slider(pipeline,
          &wavpack_bfi, "%.0f", "slider-bits-per-sample", NULL);
    }
  }

  gnac_profiles_properties_update_textbuffer(pipeline);

  g_free(wavpack_bfi.pipeline);

  wavpack_bfi.pipeline = pipeline;
}


void
gnac_profiles_wavpack_bitrate_control_on_toggle(GtkWidget       *widget,
                                                GtkToggleButton *togglebutton)
{
  GtkWidget *label = gnac_profiles_utils_get_widget(&wavpack_bfi,
      "label-control-method");
  GtkWidget *hbox = gnac_profiles_utils_get_widget(&wavpack_bfi,
      "hbox-control-method");

  if (gtk_toggle_button_get_active(togglebutton)) {
    gtk_widget_show(hbox);
    gtk_widget_show(label);
  } else {
    gtk_widget_hide(hbox);
    gtk_widget_hide(label);
  }

  gnac_profiles_wavpack_bitrate_control_on_changed(GTK_COMBO_BOX(widget));
  gnac_profiles_wavpack_generate_pipeline();
}


void
gnac_profiles_wavpack_joint_stereo_mode_on_toggle(GtkWidget       *widget,
                                                  GtkToggleButton *togglebutton)
{
  gnac_profiles_utils_on_toggle_optionnal_property(togglebutton, widget);
  gnac_profiles_wavpack_generate_pipeline();
}


static void
gnac_profiles_wavpack_reset_ui(void)
{
  gnac_profiles_default_reset_ui(&wavpack_bfi);
  gnac_profiles_utils_reset_values(&wavpack_bfi,
      "combo-mode", "combo-bitrate-control", "combo-joint-stereo-mode",
      "checkbutton-md5", "slider-bitrate", "slider-bits-per-sample",
      "slider-extra-processing", NULL);
  gnac_profiles_utils_set_active_toggle_button(&wavpack_bfi, FALSE,
      "checkbutton-bitrate-control", NULL);
}


static void
gnac_profiles_wavpack_set_fields(gpointer data)
{
  if (!data) {
    gnac_profiles_wavpack_reset_ui();
    return;
  }

  AudioProfileWavpack *profile = (AudioProfileWavpack *) data;
  gnac_profiles_default_init_fields(profile->generic, &wavpack_bfi);
  gnac_profiles_utils_set_values(&wavpack_bfi,
      "combo-mode", profile->mode,
      "slider-extra-processing", profile->extra_processing,
      "checkbutton-md5", profile->md5, NULL);
  gnac_profiles_utils_set_values_checked(&wavpack_bfi,
      "combo-joint-stereo-mode", "checkbutton-joint-stereo-mode",
      profile->joint_stereo_mode, NULL);

  GtkWidget *widget = gnac_profiles_utils_get_widget(&wavpack_bfi,
      "combo-bitrate-control");
  GtkWidget *check = gnac_profiles_utils_get_widget(&wavpack_bfi,
      "checkbutton-bitrate-control");

  if (profile->bitrate != -1.0) {
    gnac_profiles_utils_set_values(&wavpack_bfi,
        "slider-bitrate", profile->bitrate, NULL);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
    gtk_combo_box_set_active(GTK_COMBO_BOX(widget), AVERAGE_BITRATE);
  } else if (profile->bits_per_sample != -1) {
    gnac_profiles_utils_set_values(&wavpack_bfi,
        "slider-bits-per-sample", profile->bits_per_sample, NULL);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
    gtk_combo_box_set_active(GTK_COMBO_BOX(widget), BITS_PER_SAMPLE);
  }
}


static gchar *
gnac_profiles_wavpack_get_combo_format_name(void)
{
  return gnac_profiles_default_get_combo_format_name(&wavpack_bfi);
}


static AudioProfileWavpack *
gnac_profiles_wavpack_audio_profile_new(void)
{
  AudioProfileWavpack *profile = g_malloc(sizeof(AudioProfileWavpack));
  
  profile->mode = NULL;
  profile->bitrate = -1;
  profile->bits_per_sample = -1;
  profile->extra_processing = -1;
  profile->joint_stereo_mode = NULL;
  profile->md5 = NULL;

  return profile;
}


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

  AudioProfileWavpack *profile = (AudioProfileWavpack *) data;
  gnac_profiles_utils_free_audio_profile_generic(profile->generic); 
  g_free(profile->mode);
  g_free(profile->joint_stereo_mode);
  g_free(profile->md5);
  g_free(profile);
}


static gpointer
gnac_profiles_wavpack_generate_audio_profile(GError **error)
{
  AudioProfileGeneric *generic = gnac_profiles_default_generate_audio_profile(
      &wavpack_bfi);
  AudioProfileWavpack *profile = gnac_profiles_wavpack_audio_profile_new();
  profile->generic = generic;

  gnac_profiles_utils_get_values_and_set(&wavpack_bfi,
      "combo-mode", &profile->mode,
      "slider-extra-processing", &profile->extra_processing,
      "checkbutton-md5", &profile->md5, NULL);
  gnac_profiles_utils_get_values_checked_combo_and_set(&wavpack_bfi,
      "combo-joint-stereo-mode", "checkbutton-joint-stereo-mode",
      &profile->joint_stereo_mode, NULL);

  GtkWidget *widget = gnac_profiles_utils_get_widget(&wavpack_bfi,
      "combo-bitrate-control");
  GtkWidget *check = gnac_profiles_utils_get_widget(&wavpack_bfi,
      "checkbutton-bitrate-control");

  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) {
    ControlMethod control_method = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));

    if (control_method == AVERAGE_BITRATE) {
      gnac_profiles_utils_get_values_and_set(&wavpack_bfi,
          "slider-bitrate", &profile->bitrate, NULL);
    } else {
      gnac_profiles_utils_get_values_and_set(&wavpack_bfi,
          "slider-bits-per-sample", &profile->bits_per_sample, NULL);
    }
  }

  return profile;
}


static GtkWidget *
gnac_profiles_wavpack_get_widget(void)
{
  return gnac_profiles_default_get_properties_alignment(&wavpack_bfi);
}


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

  gchar *bitrate = NULL;
  gchar *bits_per_sample = NULL;
  AudioProfileWavpack *profile = (AudioProfileWavpack *) data;

  if (profile->bitrate != -1) {
    bitrate = gnac_profiles_utils_gdouble_to_gchararray(profile->bitrate);
  } else if (profile->bits_per_sample != -1) {
    bits_per_sample = gnac_profiles_utils_gdouble_to_gchararray(
        profile->bits_per_sample);
  }

  gchar *extra_processing = gnac_profiles_utils_gdouble_to_gchararray(
      profile->extra_processing);

  XMLDoc *doc = gnac_profiles_default_save_profile(profile->generic,
      &wavpack_bfi);
  gnac_profiles_xml_engine_add_values(doc,
      "mode", profile->mode,
      "bitrate", bitrate,
      "bits-per-sample", bits_per_sample,
      "extra-processing", extra_processing,
      "joint-stereo-mode", profile->joint_stereo_mode,
      "md5", profile->md5,
      NULL);
  gnac_profiles_xml_engine_save_doc(doc, profile->generic->name);

  gnac_profiles_xml_engine_free_doc_xpath(doc);
  g_free(bitrate);
  g_free(bits_per_sample);
  g_free(extra_processing);
}


static gpointer
gnac_profiles_wavpack_load_specific_properties(XMLDoc              *doc,
                                               AudioProfileGeneric *generic)
{
  gchar *bitrate;
  gchar *bits_per_sample;
  gchar *extra_processing;
  
  AudioProfileWavpack *profile = gnac_profiles_wavpack_audio_profile_new();
  profile->generic = generic;
  gnac_profiles_utils_load_saved_profile(doc,
      "/audio-profile/format-specific/",
      "mode", &profile->mode,
      "bitrate", &bitrate,
      "bits-per-sample", &bits_per_sample,
      "extra-processing", &extra_processing,
      "joint-stereo-mode", &profile->joint_stereo_mode,
      "md5", &profile->md5,
      NULL);

  profile->extra_processing = gnac_profiles_utils_gchararray_to_gdouble(
      extra_processing);
  g_free(extra_processing);

  if (bitrate) {
    profile->bitrate = gnac_profiles_utils_gchararray_to_gdouble(bitrate);
    g_free(bitrate);
  } else if (bits_per_sample) {
    profile->bits_per_sample = gnac_profiles_utils_gchararray_to_gdouble(
        bits_per_sample);
    g_free(bits_per_sample);
  }

  return profile;
}


static void
gnac_profiles_wavpack_clean_up(void)
{
  gnac_profiles_default_clean_up(&wavpack_bfi);
  gnac_profiles_utils_free_values(&wavpack_bfi,
      "combo-bitrate-control", "combo-mode", "combo-joint-stereo-mode",
      "checkbutton-md5", "slider-bitrate", "slider-bits-per-sample",
      "slider-extra-processing", NULL);
  gnac_profiles_utils_free_basic_format_info(&wavpack_bfi);
}


static const gchar *
gnac_profiles_wavpack_get_plugin_name(void)
{
  return wavpack_bfi.format_plugin_name;
}


static const gchar *
gnac_profiles_wavpack_get_description(void)
{
  return wavpack_bfi.description;
}


FormatModuleFuncs
gnac_profiles_wavpack_get_funcs(void)
{
  FormatModuleFuncs funcs = {
    gnac_profiles_wavpack_init,
    gnac_profiles_wavpack_get_description,
    gnac_profiles_wavpack_generate_pipeline,
    gnac_profiles_wavpack_generate_audio_profile,
    gnac_profiles_wavpack_free_audio_profile,
    gnac_profiles_wavpack_set_fields,
    gnac_profiles_wavpack_get_widget,
    gnac_profiles_wavpack_save_profile,
    gnac_profiles_wavpack_load_specific_properties,
    gnac_profiles_wavpack_clean_up,
    NULL,
    gnac_profiles_wavpack_get_combo_format_name,
    gnac_profiles_wavpack_get_plugin_name
  };

  return funcs;
}
