
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
 *
 * Copyright (C) 2013, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
 *
 * 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
 *
 */
#include <unistd.h>

#include "babel.h"
#include "babel_ui.h"
#include "viking.h"
#include "viktrwlayer_export.h"
#include "gpx.h"

static gchar *last_folder_uri = NULL;

#define VIK_PREFS_EXPORT_DEVICE_SIMPLIFY VIKING_PREFERENCES_IO_NAMESPACE"external_auto_device_gpx_simplify"

#define VIK_SETTINGS_EXPORT_DEVICE_PATH "export_device_path"
#define VIK_SETTINGS_EXPORT_DEVICE_SIMPLIFY_TRACKPOINT_LIMIT "export_device_trackpoint_limit"
#define VIK_SETTINGS_EXPORT_DEVICE_SIMPLIFY_ROUTEPOINT_LIMIT "export_device_routepoint_limit"

static VikLayerParam io_prefs[] = {
  { VIK_LAYER_NUM_TYPES, VIK_PREFS_EXPORT_DEVICE_SIMPLIFY, VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Auto Device GPX Simplify:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL,
     N_("GPX saves to certain devices will be simplified for device compatibility."), vik_lpd_false_default, NULL, NULL },
};

void vik_trw_layer_export_init ()
{
  a_preferences_register ( &io_prefs[0], (VikLayerParamData){0}, VIKING_PREFERENCES_IO_GROUP_KEY );
}

static gboolean gpx_export_simplify_layer ( VikTrwLayer *vtl, const gchar *fn, VikTrack* trk )
{
  // Note GPSBabel simplify has single value applied to tracks and routes
  // Try to use the best value
  // However this means if there is a mixture of tracks and routes,
  //  the tracks will be over-simplified
  // The defaults are for Garmin Edge series
  gint tmp;
  guint limit = 10000; // ETrex 20 is 500
  if ( a_settings_get_integer ( VIK_SETTINGS_EXPORT_DEVICE_SIMPLIFY_TRACKPOINT_LIMIT, &tmp ) )
    limit = tmp;

  // If any routes - apply route limit as that's normally alot lower
  gboolean got_route = FALSE;
  if ( trk )
    got_route = trk->is_route;

  if ( got_route || g_hash_table_size(vik_trw_layer_get_routes(vtl)) ) {
    if ( a_settings_get_integer ( VIK_SETTINGS_EXPORT_DEVICE_SIMPLIFY_ROUTEPOINT_LIMIT, &tmp ) )
      limit = tmp;
    else
      limit = 250; // Route capacity is relatively limited
    // NB If there are tracks and trackpoints much > (route)limit,
    //  could warn that tracks may be overily simplified
    // and ask to continue...
  }

  gboolean need_simplify = FALSE;
  if ( trk ) {
    if ( vik_track_get_tp_count(trk) > limit )
      need_simplify = TRUE;
  }
  else {
    // Check all tracks & routes in the layer
    gpointer key, value;
    GHashTableIter ght_iter;
    // See if any tracks exceed point number limit
    g_hash_table_iter_init ( &ght_iter, vik_trw_layer_get_tracks ( vtl ) );
    while ( g_hash_table_iter_next (&ght_iter, &key, &value) ) {
      if ( vik_track_get_tp_count (VIK_TRACK(value)) > limit ) {
        need_simplify = TRUE;
        break;
      }
    }
    if ( !need_simplify ) {
      // See if any routes exceed point number limit
      g_hash_table_iter_init ( &ght_iter, vik_trw_layer_get_routes ( vtl ) );
      while ( g_hash_table_iter_next (&ght_iter, &key, &value) ) {
        if ( vik_track_get_tp_count (VIK_TRACK(value)) > limit ) {
          need_simplify = TRUE;
          break;
        }
      }
    }
  }

  gboolean ans = FALSE;

  if ( need_simplify ) {
    if ( a_babel_available() ) {
      gchar *filter = g_strdup_printf ( "-x simplify,count=%d -o gpx", limit );
      ans = a_babel_convert_to ( vtl, trk, filter, fn, NULL, NULL );
      g_free ( filter );
      if ( ans ) {
         gchar *msg = g_strdup_printf ( _("Export of GPX file simplified using point limit: %d"), limit );
         a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), msg );
         g_free ( msg );
      }
    }
  }

  return ans;
}

static gboolean gpx_export ( VikTrwLayer *vtl, const gchar *fn, VikTrack* trk )
{
  // Note one could attempt to detect which device it is being saved to
  // e.g. using libusb-1.0 - example:
  // https://github.com/libusb/libusb/blob/master/examples/testlibusb.c +
  // http://www.linux-usb.org/usb.ids
  // And then knowledge of which GPSes have differing limits.
  // It might not be possible to differentiate between devices if the USB id is the same
  // e.g. Etrex 20 vs Etrex 30 - but I think these have the same limitations.
  //  and whether file is actually being saved on to the device(s) detected
  gboolean auto_simplify = a_preferences_get (VIK_PREFS_EXPORT_DEVICE_SIMPLIFY)->b;
  if ( auto_simplify ) {
    // Check path of 'fn' for device match
    gchar *device_path = NULL;
    if ( !a_settings_get_string ( VIK_SETTINGS_EXPORT_DEVICE_PATH, &device_path ) ) {
#ifdef WINDOWS
      device_path = g_strdup (":\Garmin\GPX");
#else
      device_path = g_strdup_printf ( "/media/%s/GARMIN/Garmin/GPX", g_getenv("USER") );
#endif
    }
    gboolean simplified = FALSE;
    if ( g_strrstr(fn, device_path) ) {
      simplified = gpx_export_simplify_layer ( vtl, fn, trk );
    }
    g_free ( device_path );
    if ( simplified )
      return TRUE;
  }

  return a_file_export ( vtl, fn, FILE_TYPE_GPX, trk, trk ? TRUE : FALSE );
}

/**
 * vik_trw_layer_export:
 *
 * @vl: The #VikLayer to operate on
 *
 * Note since we now use the #VikLayer type rather than #VikTrwLayer,
 *  this function could be renamed and shifted into the appropriate file.
 * However for now leave it as is.
 */
void vik_trw_layer_export ( VikLayer *vl, const gchar *title, const gchar* default_name, VikTrack* trk, VikFileType_t file_type )
{
  GtkWidget *file_selector;
  gboolean failed = FALSE;
  file_selector = gtk_file_chooser_dialog_new (title,
                                               NULL,
                                               GTK_FILE_CHOOSER_ACTION_SAVE,
                                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                               GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                               NULL);
  if ( last_folder_uri )
    gtk_file_chooser_set_current_folder_uri ( GTK_FILE_CHOOSER(file_selector), last_folder_uri );

  gtk_file_chooser_set_current_name ( GTK_FILE_CHOOSER(file_selector), default_name );

  GtkWidget *dialog = file_selector;
  GtkFileFilter *filter;
  switch ( file_type ) {
  case FILE_TYPE_GPX:
    filter = gtk_file_filter_new ();
    gtk_file_filter_set_name( filter, _("GPX") );
    gtk_file_filter_add_mime_type ( filter, "gpx+xml");
    gtk_file_filter_add_pattern ( filter, "*.gpx" );
    gtk_file_chooser_add_filter ( GTK_FILE_CHOOSER(dialog), filter );
    gtk_file_chooser_set_filter ( GTK_FILE_CHOOSER(dialog), filter );
    break;
  case FILE_TYPE_KML:
    filter = gtk_file_filter_new ();
    gtk_file_filter_set_name( filter, _("Google Earth") );
    gtk_file_filter_add_mime_type ( filter, "application/vnd.google-earth.kml+xml");
    gtk_file_chooser_add_filter ( GTK_FILE_CHOOSER(dialog), filter);
    gtk_file_chooser_set_filter ( GTK_FILE_CHOOSER(dialog), filter );
    break;
  default: break;
  }
  filter = gtk_file_filter_new ();
  gtk_file_filter_set_name( filter, _("All") );
  gtk_file_filter_add_pattern ( filter, "*" );
  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);

  while ( gtk_dialog_run ( GTK_DIALOG(file_selector) ) == GTK_RESPONSE_ACCEPT )
  {
    gchar *fn = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) );
    if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == FALSE ||
         a_dialog_yes_or_no ( GTK_WINDOW(file_selector), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) )
    {
      g_free ( last_folder_uri );
      last_folder_uri = gtk_file_chooser_get_current_folder_uri ( GTK_FILE_CHOOSER(file_selector) );

      gtk_widget_hide ( file_selector );
      vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vl)) );
      switch ( vl->type ) {
      case VIK_LAYER_TRW:
        // Don't Export invisible items - unless requested on this specific track
        if ( file_type == FILE_TYPE_GPX )
          failed = ! gpx_export ( VIK_TRW_LAYER(vl), fn, trk );
        else
          failed = ! a_file_export ( VIK_TRW_LAYER(vl), fn, file_type, trk, trk ? TRUE : FALSE );
        break;
      case VIK_LAYER_AGGREGATE:
        failed = ! vik_aggregate_layer_export_gpx_main ( VIK_AGGREGATE_LAYER(vl), NULL, fn );
        break;
      default:
        g_critical ( "%s:%s %d", __FUNCTION__, "Export not expected for layer type", vl->type ); break;
      }
      vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vl)) );
      g_free ( fn );
      break;
    }
    g_free ( fn );
  }
  gtk_widget_destroy ( file_selector );
  if ( failed )
    a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vl), _("The filename you requested could not be opened for writing.") );
}


/**
 * vik_trw_layer_export_gpx_waypoints:
 *
 * Just the waypoints of the layer are saved into a GPX file
 *
 */
void vik_trw_layer_export_gpx_waypoints ( VikTrwLayer *vtl )
{
  GtkWidget *file_chooser = gtk_file_chooser_dialog_new ( _("Export Waypoints"),
                                                          NULL,
                                                          GTK_FILE_CHOOSER_ACTION_SAVE,
                                                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                                          GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                                          NULL );
  if ( last_folder_uri )
    gtk_file_chooser_set_current_folder_uri ( GTK_FILE_CHOOSER(file_chooser), last_folder_uri );

  gchar* default_name = g_strconcat ( vik_layer_get_name(VIK_LAYER(vtl)),
                                      "_",
                                      _("Waypoints"),
                                      ".gpx",
                                      NULL );

  gtk_file_chooser_set_current_name ( GTK_FILE_CHOOSER(file_chooser), default_name );

  g_free ( default_name );

  gtk_widget_show_all ( file_chooser );

  while ( gtk_dialog_run ( GTK_DIALOG(file_chooser) ) == GTK_RESPONSE_ACCEPT ) {
    gchar *fn = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_chooser) );
    if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == FALSE ||
         a_dialog_yes_or_no ( GTK_WINDOW(file_chooser), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) ) {
      g_free ( last_folder_uri );
      last_folder_uri = gtk_file_chooser_get_current_folder_uri ( GTK_FILE_CHOOSER(file_chooser) );

      vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) );

      GpxWritingOptions options = { FALSE, FALSE, FALSE, FALSE, vik_trw_layer_get_gpx_version(vtl) };
      FILE *ff = g_fopen ( fn, "w" );
      if ( ff ) {
        a_gpx_write_waypoints_file ( vtl, ff, &options );
        fclose ( ff );
      } else {
        g_warning ( "%s: Could not save to %s", __FUNCTION__, fn );
      }

      vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) );
    }
    g_free ( fn );
    break;
  }

  gtk_widget_destroy ( file_chooser );
}

/**
 * vik_trw_layer_export_seperate_gpx:
 *
 * Export each individual track or route as a separate GPX file into the selected directory
 * Any existing file of the same name will not be overwritten.
 * Hence works better if the names are unique.
 * Otherwise only the first one will be written (provided that filename itself doesn't exist already)
 *
 */
void vik_trw_layer_export_separate_gpx ( VikTrwLayer *vtl, trw_subtype_enum subtype )
{
  GtkWidget *file_chooser = gtk_file_chooser_dialog_new ( _("Select output directory"),
                                                          NULL,
                                                          GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
                                                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                                          GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
                                                          NULL );
  if ( last_folder_uri )
    gtk_file_chooser_set_current_folder_uri ( GTK_FILE_CHOOSER(file_chooser), last_folder_uri );

  gtk_widget_show_all ( file_chooser );

  gboolean all_saved = TRUE;

  while ( gtk_dialog_run ( GTK_DIALOG(file_chooser) ) == GTK_RESPONSE_ACCEPT ) {
    gchar *folder = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_chooser) );

    vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) );

    g_free ( last_folder_uri );
    last_folder_uri = gtk_file_chooser_get_current_folder_uri ( GTK_FILE_CHOOSER(file_chooser) );

    GHashTableIter iter;
    gpointer key, value;

    switch ( subtype ) {
    case VIK_TRW_LAYER_SUBLAYER_TRACKS:
      {
        g_hash_table_iter_init ( &iter, vik_trw_layer_get_tracks(vtl) );
        while ( g_hash_table_iter_next(&iter, &key, &value) ) {
          VikTrack *trk = VIK_TRACK(value);
          if ( trk->visible ) {
            gchar *fn = g_strconcat ( folder,
                                      G_DIR_SEPARATOR_S,
                                      trk->name,
                                      a_file_check_ext(trk->name, ".gpx") ? NULL : ".gpx",
                                      NULL );
            if ( g_file_test(fn, G_FILE_TEST_EXISTS) ) {
              g_message ( _("Not overwriting existing file '%s'"), fn );
              all_saved = FALSE;
            }
            else
              gpx_export ( vtl, fn, VIK_TRACK(value) );
            g_free ( fn );
          }
        }
      }
      break;
    case VIK_TRW_LAYER_SUBLAYER_ROUTES:
      {
        g_hash_table_iter_init ( &iter, vik_trw_layer_get_routes(vtl) );
        while ( g_hash_table_iter_next(&iter, &key, &value) ) {
          VikTrack *trk = VIK_TRACK(value);
          if ( trk->visible ) {
            gchar *fn = g_strconcat ( folder,
                                      G_DIR_SEPARATOR_S,
                                      trk->name,
                                      a_file_check_ext(trk->name, ".gpx") ? NULL : ".gpx",
                                      NULL );
            if ( g_file_test(fn, G_FILE_TEST_EXISTS) ) {
              g_message ( _("Not overwriting existing file '%s'"), fn );
              all_saved = FALSE;
            }
            else
              gpx_export ( vtl, fn, VIK_TRACK(value) );
            g_free ( fn );
          }
        }
      }
      break;
    default:
      g_critical ( "%s: Should not use %d", __FUNCTION__, subtype );
      break;
    }

    vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) );

    g_free ( folder );
    break;
  }

  gtk_widget_destroy ( file_chooser );

  if ( !all_saved )
    a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
                           _("Not all sublayers could be saved. Check the main log for details.") );
}


/**
 * Convert the given TRW layer into a temporary GPX file and open it with the specified program
 *
 */
void vik_trw_layer_export_external_gpx ( VikTrwLayer *vtl, const gchar* external_program )
{
  // Don't Export invisible items
  GpxWritingOptions options = { TRUE, TRUE, FALSE, FALSE, vik_trw_layer_get_gpx_version(vtl) };
  gchar *name_used = a_gpx_write_tmp_file ( vtl, &options );

  if ( name_used ) {
    GError *err = NULL;
    gchar *quoted_file = g_shell_quote ( name_used );
    gchar *cmd = g_strdup_printf ( "%s %s", external_program, quoted_file );
    g_free ( quoted_file );
    g_message ( "%s: %s", __FUNCTION__, cmd );
    if ( ! g_spawn_command_line_async ( cmd, &err ) ) {
      a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_LAYER( vtl), _("Could not launch %s"), external_program );
      g_error_free ( err );
    }
    g_free ( cmd );
    util_add_to_deletion_list ( name_used );
    g_free ( name_used );
  }
  else
    a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Could not create temporary file for export.") );
}

static guint last_mode_index = 0;
static BabelMode last_mode = { 0, 0, 0, 0, 0, 0 };
static gchar* last_suboptions = NULL;

gboolean BabelMode_is_equal ( BabelMode left, BabelMode right )
{
  return ( left.waypointsRead == right.waypointsRead &&
           left.waypointsWrite == right.waypointsWrite &&
           left.tracksRead == right.tracksRead &&
           left.tracksWrite == right.tracksWrite &&
           left.routesRead == right.routesRead &&
           left.routesWrite == right.routesWrite );
}

/**
 * vik_trw_layer_export_gpsbabel:
 * @vl: The #VikLayer to operate on
 *
 * Note we now use the #VikLayer type rather than #VikTrwLayer.
 * As also supports #VikAggregateLayer type
 * Similar to vik_trw_layer_export() above
 */
void vik_trw_layer_export_gpsbabel ( VikLayer *vl, const gchar *title, const gchar* default_name, const gchar* gpx_file_name )
{
  g_return_if_fail ( vl->type == VIK_LAYER_AGGREGATE || vl->type == VIK_LAYER_TRW );

  BabelMode mode = { 0, 0, 0, 0, 0, 0 };
  if ( vl->type == VIK_LAYER_TRW ) {
    mode.routesWrite    = g_hash_table_size(vik_trw_layer_get_routes(VIK_TRW_LAYER(vl))) ? 1 : 0;
    mode.tracksWrite    = g_hash_table_size(vik_trw_layer_get_tracks(VIK_TRW_LAYER(vl))) ? 1 : 0;
    mode.waypointsWrite = g_hash_table_size(vik_trw_layer_get_waypoints(VIK_TRW_LAYER(vl))) ? 1 : 0;
  } else {
    // Analyse all (visible) TRW layers to see what they contain and thus enable writing mode thereof
    GList *layers = NULL;
    layers = vik_aggregate_layer_get_all_layers_of_type ( VIK_AGGREGATE_LAYER(vl), layers, VIK_LAYER_TRW, FALSE );

    for ( GList *layer = layers; layer != NULL; layer = layer->next ) {
      if ( mode.routesWrite == 0 )
        mode.routesWrite = g_hash_table_size(vik_trw_layer_get_routes(VIK_TRW_LAYER(layer->data))) ? 1 : 0;
      if ( mode.tracksWrite == 0 )
        mode.tracksWrite = g_hash_table_size(vik_trw_layer_get_tracks(VIK_TRW_LAYER(layer->data))) ? 1 : 0;
      if ( mode.waypointsWrite == 0 )
        mode.waypointsWrite = g_hash_table_size(vik_trw_layer_get_waypoints(VIK_TRW_LAYER(layer->data))) ? 1 : 0;
    }
    g_list_free ( layers );
  }

  GtkWidget *file_selector;
  gboolean failed = FALSE;
  file_selector = gtk_file_chooser_dialog_new (title,
                                               NULL,
                                               GTK_FILE_CHOOSER_ACTION_SAVE,
                                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                               GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                               NULL);
  gchar *cwd = g_get_current_dir();
  if ( cwd ) {
    gtk_file_chooser_set_current_folder ( GTK_FILE_CHOOSER(file_selector), cwd );
    g_free ( cwd );
  }

  /* Build the extra part of the widget */
  GtkWidget *babel_selector = a_babel_ui_file_type_selector_new ( mode );
  GtkWidget *label = gtk_label_new(_("File format:"));
  GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start ( GTK_BOX(hbox), label, TRUE, TRUE, 2 );
  gtk_box_pack_start ( GTK_BOX(hbox), babel_selector, TRUE, TRUE, 2 );

  gtk_widget_set_tooltip_text( babel_selector, _("Select the file format.") );

  GtkWidget *babel_modes = a_babel_ui_modes_new(mode.tracksWrite, mode.routesWrite, mode.waypointsWrite);

  gtk_widget_set_tooltip_text( babel_modes, _("Select the information to process.\n"
      "Warning: the behavior of these switches is highly dependent of the file format selected.\n"
      "Please, refer to GPSbabel if unsure.") );

  GtkWidget *hbox2 = gtk_hbox_new(FALSE, 0);
  GtkWidget *link = gtk_link_button_new_with_label ( "https://www.gpsbabel.org/capabilities.html", _("GPSBabel suboptions") );
  GtkWidget *entry = ui_entry_new ( BabelMode_is_equal(mode, last_mode) ? last_suboptions : NULL, GTK_ENTRY_ICON_SECONDARY );
  gtk_box_pack_start ( GTK_BOX(hbox2), link, FALSE, FALSE, 2 );
  gtk_box_pack_start ( GTK_BOX(hbox2), entry, TRUE, TRUE, 2 );

  GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
  gtk_box_pack_start ( GTK_BOX(vbox), hbox, TRUE, TRUE, 2 );
  gtk_box_pack_start ( GTK_BOX(vbox), babel_modes, TRUE, TRUE, 2 );
  gtk_box_pack_start ( GTK_BOX(vbox), hbox2, TRUE, TRUE, 2 );

  gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(file_selector), vbox);

  /* Add some dynamic: only allow dialog's validation when format selection is done */
  g_signal_connect (babel_selector, "changed", G_CALLBACK(a_babel_ui_type_selector_dialog_sensitivity_cb), file_selector);
  // NB the selection list changes according to available modes, so only restore selection index if the same mode
  if ( BabelMode_is_equal(mode, last_mode) )
    gtk_combo_box_set_active ( GTK_COMBO_BOX(babel_selector), last_mode_index );
  /* Manually call the callback to fix the state */
  a_babel_ui_type_selector_dialog_sensitivity_cb ( GTK_COMBO_BOX(babel_selector), file_selector);

  /* Set possible name of the file */
  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(file_selector), default_name);

  gtk_widget_show_all ( file_selector );

  while ( gtk_dialog_run ( GTK_DIALOG(file_selector) ) == GTK_RESPONSE_ACCEPT )
  {
    gchar *fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(file_selector) );
    if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == FALSE ||
         a_dialog_yes_or_no ( GTK_WINDOW(file_selector), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) )
    {
      BabelFile *active = a_babel_ui_file_type_selector_get(babel_selector);
      if (active == NULL) {
          a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vl), _("You did not select a valid file format.") );
      } else {
        gtk_widget_hide ( file_selector );
        vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vl)) );
        gboolean tracks, routes, waypoints;
        a_babel_ui_modes_get( babel_modes, &tracks, &routes, &waypoints );
        if ( vl->type == VIK_LAYER_TRW )
          failed = ! a_file_export_babel ( VIK_TRW_LAYER(vl), NULL, fn, active->name, tracks, routes, waypoints, gtk_entry_get_text(GTK_ENTRY(entry)) );
        else {
          failed = ! a_file_export_babel ( NULL, gpx_file_name, fn, active->name, tracks, routes, waypoints, gtk_entry_get_text(GTK_ENTRY(entry)) );
        }
        vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vl)) );
        g_free ( fn );
        // Save selections for usage next time
        last_mode_index = gtk_combo_box_get_active ( GTK_COMBO_BOX(babel_selector) );
	last_mode = mode;
        if ( last_suboptions )
          g_free ( last_suboptions );
        last_suboptions = g_strdup ( gtk_entry_get_text(GTK_ENTRY(entry)) );
        break;
      }
    }
    g_free ( fn );
  }
  //babel_ui_selector_destroy(babel_selector);
  gtk_widget_destroy ( file_selector );
  if ( failed )
    a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vl), _("The filename you requested could not be opened for writing.") );
}
