/* lyric.c
 *
 * Functions for the manipulations of lyrics
 *
 * for Denemo, a gtk+ frontend for GNU Lilypond
 * (c)2009 Richard Shann
 */
#include <string.h> /* for strcmp() */
#include "lyric.h"
#include "objops.h"
#include "staffops.h"
#include "utils.h"

static GtkWidget *DummyVerse;/* a non-existent verse */

static gboolean lyric_keypress(GtkWidget *w, GdkEventKey *event) {
DenemoGUI *gui = Denemo.gui;
 if(gtk_text_buffer_get_modified(gtk_text_view_get_buffer(GTK_TEXT_VIEW(w)))) {
   score_status(Denemo.gui, TRUE);
   gtk_widget_queue_draw (Denemo.scorearea);
   gtk_text_buffer_set_modified(gtk_text_view_get_buffer(GTK_TEXT_VIEW(w)), FALSE);
 }
 return FALSE;
}
gboolean lyric_change(GtkTextBuffer *buffer) {
  DenemoGUI *gui = Denemo.gui;
  score_status(gui, TRUE);
  gtk_widget_queue_draw (Denemo.scorearea);
  return FALSE;
}

static GtkWidget *new_lyric_editor(void) {
 GtkWidget *view = gtk_text_view_new ();
 // g_signal_connect (G_OBJECT (view), "key-press-event", G_CALLBACK (lyric_keypress), NULL);
 //g_signal_connect (G_OBJECT (gtk_text_view_get_buffer(view)), "changed", G_CALLBACK (lyric_keypress), NULL);

 return view;
}

DenemoObject *
newlyric (gint baseduration, gint numdots, gchar *lys) {
  g_warning("Not implemented");
  return NULL;
}

static void
switch_page (GtkNotebook *notebook, GtkNotebookPage *page,  guint pagenum, DenemoStaff *staff) {
    gtk_widget_queue_draw (Denemo.scorearea);
    staff->currentverse = g_list_nth(staff->verses, pagenum);
}
GtkWidget * add_verse_to_staff(DenemoScore *si, DenemoStaff *staff) {
  GtkWidget *notebook, *textview;
  if(staff->verses==NULL) {
    notebook = gtk_notebook_new();
    gtk_widget_show(notebook);
    g_signal_connect (G_OBJECT(notebook), "switch_page", G_CALLBACK(switch_page), staff);
    if(si->lyricsbox==NULL)
      install_lyrics_preview(si, gtk_widget_get_parent(gtk_widget_get_parent(Denemo.scorearea)));//FIXME we need a proper way of getting to the top vbox, that will not break when scorearea is moved in the widget hierarchy.
    gtk_box_pack_start(GTK_BOX(si->lyricsbox), notebook, TRUE, TRUE, 0);
    if(si->measurewidth==DENEMO_INITIAL_MEASURE_WIDTH)
      si->measurewidth = DENEMO_INITIAL_MEASURE_WIDTH*3;
  } else {
    GtkWidget *w = staff->verses->data;
    notebook = gtk_widget_get_parent(w);
  }
  // if(staff->currentverse)    
  //  gtk_widget_hide(staff->currentverse->data); 
  //if(si->currentstaff && si->currentstaff->data == staff)
  //  gtk_widget_show(staff->currentverse->data);
  textview = new_lyric_editor();
  gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW(textview), GTK_WRAP_WORD_CHAR);
  gtk_widget_show(textview);
  staff->verses = g_list_append(staff->verses, textview);
  staff->currentverse = g_list_last(staff->verses);
  //  g_print("Setting verse to %p\n", staff->currentverse);
  gint pagenum = gtk_notebook_append_page (GTK_NOTEBOOK (notebook), textview, NULL);
  gtk_notebook_set_current_page (GTK_NOTEBOOK(notebook), pagenum);
  gchar *tablabel = g_strdup_printf("Verse %d", pagenum+1);
  gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(notebook), textview, tablabel);
  g_free(tablabel);
  if(pagenum)
    gtk_notebook_set_show_tabs (GTK_NOTEBOOK(notebook), TRUE);
  return textview;
}

void add_verse(GtkAction *action, gpointer param) {
DenemoGUI *gui = Denemo.gui;
DenemoScore *si = gui->si;
 if(gui->si->currentstaff) {
   DenemoStaff *staff = si->currentstaff->data;
   add_verse_to_staff(si, staff);
   gtk_widget_show(staff->currentverse->data);
   g_signal_connect (G_OBJECT (gtk_text_view_get_buffer (staff->currentverse->data)), "changed", G_CALLBACK (lyric_change), NULL);
 }
}

void delete_verse(GtkAction *action, gpointer param) {
DenemoGUI *gui = Denemo.gui;
DenemoScore *si = gui->si;
 if(si->currentstaff) {
   DenemoStaff *staff = si->currentstaff->data;
   if(staff->currentverse) {
     staff->verses = g_list_remove_link(staff->verses, staff->currentverse);
     gtk_widget_destroy(staff->currentverse->data);
     staff->currentverse = staff->verses;
     score_status(gui, TRUE);
     gtk_widget_queue_draw (Denemo.scorearea);
   }
 }

}


gchar *get_text_from_view(GtkWidget *textview) {
  GtkTextIter startiter, enditer; 
  GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(textview));    
  gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER(buffer), &startiter);
  gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER(buffer), &enditer);
  return gtk_text_buffer_get_text (GTK_TEXT_BUFFER(buffer), &startiter, &enditer, FALSE);
}

gboolean scan_syllable(gchar **next, GString *gs) {
  gboolean result;
  result = pango_scan_string((const char **)next, gs);
  if(result && (*gs->str=='\\') && (*(gs->str+1)!='\\') && (*(gs->str+1)!='\"')) {
    while(**next && **next!='\n')
    (*next)++;//skip to end of line
    return scan_syllable(next, gs);
  } 
  if(result && ((!strcmp(gs->str, "--")||(!strcmp(gs->str, "__")))))
     return scan_syllable(next, gs);
  return result;
}

static gchar *lyric_iterator(GtkWidget *textview, gint count) {
  static  const gchar *next;
  static gchar *lyrics;
  static GString *gs;
  static start_count;
  if(gs==NULL)
    gs = g_string_new("");
  if(textview==NULL) {
    gboolean result = scan_syllable((gchar **)&next, gs);
    if(result && gs->len)
      return gs->str;
    else
      return NULL;
  }
  if(textview != DummyVerse) {
    if(lyrics) g_free(lyrics);
    lyrics = get_text_from_view(textview);
    next = lyrics;
    start_count = count;
    while(count--)
      scan_syllable((gchar **)&next, gs);
 }
  return NULL;
}


gchar *next_syllable(gint count) {
  return lyric_iterator(NULL, count);
}


/* rename reset_lyrics */
void reset_lyrics(DenemoStaff *staff, gint count) {
  if(DummyVerse==NULL)
    DummyVerse = gtk_text_view_new();
  if(staff && staff->currentverse)
    lyric_iterator(staff->currentverse->data, count);
  else lyric_iterator(DummyVerse, count);
}



void install_lyrics_preview(DenemoScore *si, GtkWidget *top_vbox){ 
  if(si->lyricsbox==NULL)
    si->lyricsbox = gtk_vbox_new (FALSE, 1);//box to hold notebook of textview widgets
  gtk_box_pack_start (GTK_BOX (top_vbox), si->lyricsbox, FALSE, TRUE, 0);
  if (Denemo.prefs.lyrics_pane)
    gtk_widget_show(si->lyricsbox);
}

/* hide the notebook of verses for the current staff */
void hide_lyrics(void) {
DenemoGUI *gui = Denemo.gui;
DenemoScore *si = gui->si;
 if(gui->si->currentstaff && ((DenemoStaff *)gui->si->currentstaff->data)->currentverse)
   gtk_widget_hide(gtk_widget_get_parent(((DenemoStaff *)gui->si->currentstaff->data)->currentverse->data));
}

/* show the notebook of verses for the current staff */
void show_lyrics(void) {
DenemoGUI *gui = Denemo.gui;
DenemoScore *si = gui->si;
 if(si->currentstaff && ((DenemoStaff *)si->currentstaff->data)->currentverse)
   gtk_widget_show(gtk_widget_get_parent(((DenemoStaff *)si->currentstaff->data)->currentverse->data));
}

/* hide the notebooks of verses for the non-current staffs */
void select_lyrics(void) {
DenemoGUI *gui = Denemo.gui;
DenemoScore *si = gui->si;
 GList *current = si->thescore;
 for(;current;current = current->next) {
   if(current != si->currentstaff && ((DenemoStaff *)current->data)->verses)
       gtk_widget_hide(gtk_widget_get_parent(((DenemoStaff *)current->data)->verses->data));
 }
}

gchar *get_lyrics_for_current_verse(DenemoStaff *thestaff) {
  if(thestaff->currentverse && thestaff->currentverse->data)
    return get_text_from_view(thestaff->currentverse->data);
  else
    return  NULL;
}

gboolean append_lyrics_for_current_verse(DenemoStaff *thestaff, gchar *text) {
  if(thestaff->currentverse && thestaff->currentverse->data) {
    GtkTextIter iter;
    GtkTextBuffer *textbuffer = gtk_text_view_get_buffer (thestaff->currentverse->data);
    gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER(textbuffer), &iter);  
    gtk_text_buffer_insert (textbuffer, &iter, text, -1);    
    return TRUE;
  }
  else
    return FALSE;
}
gboolean put_lyrics_for_current_verse(DenemoStaff *thestaff, gchar *text) {
  if(thestaff->currentverse && thestaff->currentverse->data) {
    GtkTextBuffer *textbuffer = gtk_text_view_get_buffer (thestaff->currentverse->data);
    GtkTextIter startiter, enditer; 
    gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER(textbuffer), &startiter);
    gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER(textbuffer), &enditer);
    gtk_text_buffer_delete (textbuffer, &startiter, &enditer);   
    gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER(textbuffer), &enditer);  
    gtk_text_buffer_insert (textbuffer, &enditer, text, -1);    
    return TRUE;
  }
  else
    return FALSE;
}
