/*
  Ouvre un fichier source C, chemin absolu.
  -I/usr/include/gtksourceview-1.0 -lgtksourceview-1.0
*/
#include <gtk/gtk.h>
#include <gtksourceview/gtksourceview.h>
#include <gtksourceview/gtksourcebuffer.h>
#include <gtksourceview/gtksourcelanguage.h>
#include <gtksourceview/gtksourcelanguagesmanager.h>

/*==============================================================================
 Create a GtkSourceBuffer ******************************************************
==============================================================================*/
static GtkSourceBuffer *create_source_buffer (GtkSourceLanguagesManager *manager)
{
  GtkSourceBuffer *buffer;
  buffer = GTK_SOURCE_BUFFER (gtk_source_buffer_new (NULL));
  g_object_ref (manager);
  g_object_set_data_full (G_OBJECT (buffer), "languages-manager",manager, (GDestroyNotify) g_object_unref);
  return buffer;
}
/*==============================================================================
 Load a file *******************************************************************
==============================================================================*/
static gboolean gtk_source_buffer_load_with_encoding (GtkSourceBuffer *source_buffer,
		const gchar *filename, const gchar *encoding, GError **error)
{
  GIOChannel *io;
  GtkTextIter iter;
  gchar *buffer;
  gboolean reading;

  g_return_val_if_fail (source_buffer != NULL, FALSE);
  g_return_val_if_fail (filename != NULL, FALSE);
  g_return_val_if_fail (GTK_IS_SOURCE_BUFFER (source_buffer), FALSE);

  *error = NULL;

  io = g_io_channel_new_file (filename, "r", error);
  if (!io)
  {
    //error_dialog (NULL, "%s\nFile %s", (*error)->message, filename);
    g_print("erreur: %s %s\n", (*error)->message, filename);
    return FALSE;
  }

  if (g_io_channel_set_encoding (io, encoding, error) != G_IO_STATUS_NORMAL)
  {
   //error_dialog (NULL, "Failed to set encoding:\n%s\n%s", filename, (*error)->message);
   g_print("erreur: Failed to set encoding:\n%s\n%s", filename, (*error)->message);
   return FALSE;
  }

  gtk_source_buffer_begin_not_undoable_action (source_buffer);

  gtk_text_buffer_set_text (GTK_TEXT_BUFFER (source_buffer), "", 0);
  buffer = g_malloc (4096);
  reading = TRUE;
  while (reading)
  {
    gsize bytes_read;
    GIOStatus status;
	
    status = g_io_channel_read_chars (io, buffer, 4096, &bytes_read, error);
    switch (status)
    {
      case G_IO_STATUS_EOF:
        reading = FALSE;
        /* fall through */
	
      case G_IO_STATUS_NORMAL:
        if (bytes_read == 0)
        {
          continue;
        }		
        gtk_text_buffer_get_end_iter ( GTK_TEXT_BUFFER (source_buffer), &iter);
        gtk_text_buffer_insert (GTK_TEXT_BUFFER (source_buffer), &iter, buffer, bytes_read);
        break;

      case G_IO_STATUS_AGAIN:
        continue;

      case G_IO_STATUS_ERROR:
      default:
        //error_dialog (NULL, "%s\nFile %s", (*error)->message, filename);
        g_print("erreur:%s\nFile %s", (*error)->message, filename);
        // because of error in input we clear already loaded text
        gtk_text_buffer_set_text (GTK_TEXT_BUFFER (source_buffer), "", 0);

        reading = FALSE;
        break;
      }
  }
  g_free (buffer);

  gtk_source_buffer_end_not_undoable_action (source_buffer);
  g_io_channel_unref (io);
    
  if (*error) return FALSE;

  gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (source_buffer), FALSE);

  /* move cursor to the beginning */
  gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (source_buffer), &iter);
  gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (source_buffer), &iter);
   
  return TRUE;
}

/*==============================================================================
 Create a GtkSourceBuffer ******************************************************
==============================================================================*/
static gboolean open_file (GtkSourceBuffer *buffer, const gchar *filename)
{
  GtkSourceLanguagesManager *manager;
  GtkSourceLanguage *language = NULL;
  GError *err = NULL;

  /* get the new language for the file mimetype */
  manager = g_object_get_data (G_OBJECT (buffer), "languages-manager");
  language = gtk_source_languages_manager_get_language_from_mime_type (manager, "text/x-csrc");

  //  gchar*      gtk_source_language_get_name    (GtkSourceLanguage *language);
  g_print("Langage: [%s]\n", gtk_source_language_get_name(language));

  if (language == NULL)
  {
    g_print ("No language found for mime type `%s'\n", "text/x-csrc");
    g_object_set (G_OBJECT (buffer), "highlight", FALSE, NULL);
  }
  else
  {	
   g_object_set (G_OBJECT (buffer), "highlight", TRUE, NULL);
   gtk_source_buffer_set_language (buffer, language);
  }


  gtk_source_buffer_load_with_encoding (buffer, filename, "utf-8", &err);
  g_object_set_data_full (G_OBJECT (buffer),"filename", g_strdup (filename),(GDestroyNotify) g_free);

  if (err != NULL)
  {
   g_error_free (err);
   return FALSE;
  }
  return TRUE;
}
/*==============================================================================
 Entry point *******************************************************************
==============================================================================*/
int main( int argc, char *argv[] )
{
  static GtkWidget *fenetre, *pScrollWin, *sView;
  GtkSourceLanguagesManager *lm;
  GtkSourceBuffer *sBuf;

  // Creation fenetre
  gtk_init (&argc, &argv);
  fenetre = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  g_signal_connect(G_OBJECT(fenetre),"destroy",G_CALLBACK(gtk_main_quit),NULL);
  gtk_container_set_border_width (GTK_CONTAINER (fenetre), 10);
  gtk_window_set_default_size(GTK_WINDOW(fenetre), 800, 400);
  gtk_window_set_position (GTK_WINDOW (fenetre), GTK_WIN_POS_CENTER);

  // Charge scrolledWindow qui contient le sourceView
  pScrollWin = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (pScrollWin),
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

  // Creation source_view
  lm = gtk_source_languages_manager_new();
  sBuf = create_source_buffer(lm);
  sView = gtk_source_view_new_with_buffer(sBuf);

  // Attache scrollWin a la fenetre
  gtk_container_add (GTK_CONTAINER (pScrollWin), GTK_WIDGET (sView));
  gtk_container_add (GTK_CONTAINER (fenetre), pScrollWin);
  gtk_widget_show_all (pScrollWin);

  //if (argc > 1) // Chargement d'un fichier
  //  open_file (sBuf, argv [1]);
  //else
    open_file (sBuf, (argc > 1)?argv[1]:"src.c");

  gtk_widget_show (fenetre);
  gtk_main();

  g_object_unref (sBuf); // cleanup

  return 0;
}