/*
Copyright (C) 2002, 2003 Brian Victor Fernandes

This file is part of XMMS mp3cue.

XMMS mp3cue 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.

XMMS mp3cue 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 XMMS mp3cue; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

XMMS mp3cue: http://brianvictor.tripod.com/mp3cue.htm
Email: brianv@phreaker.net

Brian Fernandes
503, Miaami Apts. II,
St. Vincents Street,
Pune 411001
INDIA
*/
	    
#include <pthread.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "configfile.h"
#include <stdio.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>

#include <unistd.h>
#include <malloc.h>
#include "defs.h"
#include "xmmsctrl.h" 
#include <plugin.h>


#define CONFIGFILE "/.xmms/mp3cue"
extern gint time_width;


// the funtions 

static gint mp3cue_thread(gpointer);
void mp3cue_init(void);
void mp3cue_config(void);
void mp3cue_config_save(GtkWidget *wid, gpointer data);
void mp3cue_cleanup(void);

extern void mp3cue_about(void);
extern void fixcolors(gint redrow, gint blackrow);
extern int find_cue_sheet(gint);
extern void clean_list();


void hide_list(GtkWidget *playlist, gpointer data);
void nextsong();
void prevsong();
gint findsong(int time);


gboolean play_sub_song(GtkWidget *song_list, gint row, gint column, GdkEvent *event);
void showMainMenu();
gboolean update_sub_playlist(GtkWidget *song_list, GdkEventButton *event);
void remove_sub_song(GtkWidget *song_list, GdkEventButton *event);
void edit_sub_song(GtkWidget *song_list, GdkEventButton *event);


//global variables, pertaining to the dialogs
extern GtkWidget *song_name;
extern GtkWidget *song_artist;
extern GtkWidget *album_name;
extern GtkWidget *album_artist;
extern GtkWidget *song_sec;
extern GtkWidget *song_min;
extern GtkWidget *song_frame;
extern GtkWidget *g_playlist;
extern GtkWidget *sub_playlist;
extern GtkWidget *song_menu;
extern GtkWidget *main_menu;

extern void create_About();
extern void create_Add_Song();
extern GtkWidget* create_Playlist (void); 


gchar *album_name_s;
gchar *album_artist_s;

//Miscellaneous Global variables
static gint timeout_tag = 0;
static gint previous_song = -1, previous_length = -2;
gint rows = 0, s_row = -1, p_row = -1, n_row = -1;
char list_visible = 1;
int n_time,c_time;
GdkEventButton two_button_event;


GeneralPlugin mp3cue =
{
	NULL,
	NULL,
	-1,
	"XMMS mp3cue "VERSION,
	mp3cue_init,
	create_About,
	mp3cue_config,
	mp3cue_cleanup,
};


void hide_list(GtkWidget *playlist, gpointer data) 
{
  gtk_widget_hide(playlist);
  list_visible = 0;
}

void nextsong()
{
  if(gtk_clist_get_selectable(GTK_CLIST(sub_playlist), p_row+1)) { 
    two_button_event.type = GDK_2BUTTON_PRESS;
    play_sub_song(sub_playlist, p_row+1, 0,(GdkEvent *) &two_button_event);
  }
}

void prevsong()
{
  if(p_row > 0) {
    two_button_event.type = GDK_2BUTTON_PRESS;
    play_sub_song(sub_playlist, p_row-1, 0,(GdkEvent *) &two_button_event);
  }
}


void fixtimes(gint c_row) 
{
  gchar *ntimed;
  gchar *data;
  static gchar title[100];
  gint min, sec, frame;
  //also get the time of the next song in the list
  if(gtk_clist_get_text(GTK_CLIST(sub_playlist), c_row+1, 1, &ntimed)) {
    SCANTIME(ntimed,min,sec,frame);
    n_time = MSEC(min, sec, frame);
    //set the window title
  }
  else n_time = xmms_remote_get_playlist_time(mp3cue.xmms_session, xmms_remote_get_playlist_pos(mp3cue.xmms_session));

  //now set the title
  
  if(gtk_clist_get_text(GTK_CLIST(sub_playlist), c_row, 0, &data)) {
    strcpy(title, "mp3cue ~ ");
    strncat(title, strrchr(data,'~')+2,100-strlen(title)-1);
    gtk_window_set_title(GTK_WINDOW(g_playlist), title);
  }

  else gtk_window_set_title(GTK_WINDOW(g_playlist), "mp3cue Playlist");

#ifdef DEBUG
  printf("\nNext song at %d msec or %d minutes",n_time,n_time/(60*1000));
#endif

}



gboolean play_sub_song(GtkWidget *song_list,
                         gint row,
                         gint column,
                         GdkEvent *event) {


  if(!event || event->type == GDK_2BUTTON_PRESS) {
    //get the text int the selected row
    gchar *timed;
    gint min, sec, frame;

    gtk_clist_get_text(GTK_CLIST(song_list), row, 1, &timed);
    SCANTIME(timed,min,sec,frame);
    if(!xmms_remote_is_playing(mp3cue.xmms_session))  xmms_remote_play(mp3cue.xmms_session);
    xmms_remote_jump_to_time(mp3cue.xmms_session, MSEC(min, sec, frame));

    //make playlist changes immediately ... 
    //we need to check whether xmms has jumped in order to accomodate for impossible time data
    int c_row = findsong(xmms_remote_get_output_time(mp3cue.xmms_session));
    fixtimes(c_row);
    fixcolors(c_row, p_row);
    p_row = c_row;

    return TRUE;
  }


  return FALSE;
}


void showMainMenu(GtkWidget *dummy, GdkEventButton *event)
{
  if(event->button == 3) {
    s_row = -1;
    gtk_menu_popup(GTK_MENU(main_menu), NULL, NULL, NULL, NULL, 3, event->time);
  }
}


gboolean update_sub_playlist(GtkWidget *song_list, GdkEventButton *event) {
  gint col;
  s_row = -1;
  if(event->button == 3) {
    gtk_clist_get_selection_info(GTK_CLIST(sub_playlist), (gint)event->x, (gint)event->y, &s_row, &col);
    if(s_row >= 0) gtk_menu_popup(GTK_MENU(song_menu), NULL, NULL, NULL, NULL, 3, event->time);
    else       //okey dokey display the main menu
      gtk_menu_popup(GTK_MENU(main_menu), NULL, NULL, NULL, NULL, 3, event->time);
    return TRUE;
  }
  return FALSE;
}

void remove_sub_song(GtkWidget *song_list, GdkEventButton *event) {
  if(event->button == 1) {
    gtk_clist_remove(GTK_CLIST(sub_playlist), s_row);
    rows--;
    //update our globals

    //if update or add, we have to fix up the time
    p_row = findsong(xmms_remote_get_output_time(mp3cue.xmms_session));
    fixtimes(p_row);
    
    clean_list();
    fixcolors(p_row, -1);
  }
 
}


void edit_sub_song(GtkWidget *song_list, GdkEventButton *event) {
  if(event->button == 1) {
    create_Add_Song();
  }
}

// simply stop the running thread if running plugin gets disabled 
void mp3cue_cleanup(void)
{
  if(timeout_tag) gtk_timeout_remove(timeout_tag);
  timeout_tag = 0;
  //close the window
  gtk_widget_destroy(main_menu);
  gtk_widget_destroy(song_menu);
  gtk_widget_destroy(g_playlist);
  //pthread_cancel (tid);
}

// required by xmms to display info line 
extern "C" {
  GeneralPlugin *get_gplugin_info(void)
  {
    return (&mp3cue);
  }
}


// initialization of the plugin 

void mp3cue_init(void)
{
  //read_config(NULL, NULL);
  previous_song = -1;
  previous_length = -2;
  timeout_tag = gtk_timeout_add(500, mp3cue_thread, NULL);
  g_playlist = create_Playlist(); //playlist should be create only once, at the beginning, thereafter, it cannot be deleted but only hidden
}



gint findsong(int time) 
{
  //to find the song that corresponds to the current time
  gchar *timed;
  gint row = 0;
  gint min, sec, frame;
  while(gtk_clist_get_text(GTK_CLIST(sub_playlist), row++, 1, &timed)) {
    SCANTIME(timed, min, sec, frame);
    if(MSEC(min, sec, frame) > time) break;
  }
  //the previous row will be the song we want read the time
  row-=2;
  if(gtk_clist_get_text(GTK_CLIST(sub_playlist), row, 1, &timed)) {
    SCANTIME(timed, min, sec, frame);
    c_time = MSEC(min, sec, frame);
  }
  else c_time = 0;

#ifdef DEBUG
  printf("\nFound song at Row:%d , %d mins",row,c_time/(60*1000));
#endif

  return row;
}

// the main part 

static gint mp3cue_thread(gpointer data)
{
  gint pos, length, o_time, c_row;

  GDK_THREADS_ENTER();

  //check whether we should change the highlighting for the currently playing song
  if(xmms_remote_is_playing(mp3cue.xmms_session)) {
    o_time = xmms_remote_get_output_time(mp3cue.xmms_session);
    if(o_time >= n_time || o_time < c_time) {
      //ok, since we have moved, we must now find the new sub song to highlight
      c_row = findsong(o_time);
      fixtimes(c_row);
      fixcolors(c_row, p_row);
      p_row = c_row;
    }
  }
  
  //song change
  pos = xmms_remote_get_playlist_pos(mp3cue.xmms_session);
  length = xmms_remote_get_playlist_time(mp3cue.xmms_session, pos);
  
  if (pos != previous_song || length != previous_length) {
    previous_song = pos;
    previous_length = length;
    gtk_clist_clear(GTK_CLIST(sub_playlist));
    //now we should be loading another playlist if present.. for now, it isn't so..
    rows = 0;
    c_time = 0;
    n_time = length;
    p_row = -1;
    //clear the current album name and artist.. 
    if(album_name_s) free(album_name_s);
    if(album_artist_s) free(album_artist_s);
    album_name_s = NULL;
    album_artist_s = NULL;
    //get the new name
    find_cue_sheet(pos);
  }

  GDK_THREADS_LEAVE();
  
  return TRUE;
}




// the config window ... currently just toggles the mp3cue playlist


void mp3cue_config(void) 
{
  if(list_visible)  {
    gtk_widget_hide(g_playlist);
    list_visible = 0;
  }
 else {
   gtk_widget_show(g_playlist);
   list_visible = 1;
 }
}










//General algorithm for loading up the correct cue sheets and highlighting the current song in the mp3cue playlist

//Every 500 Msec.. check if we have a new song.
//    if so, then set p_row to -1. Set c_time to 0 and n_time to song end


//also check if we have our output time below c_time or above n_time
//   if so, we must find the song at the current output time.
//   then fix c_time and n_time for that song.
//   change the highlighting

//if we add a song, then all the p_row info could be messed up, also the currently playing song could change.
//so get p_row data (time) before adding.
//when we add the data
//if p_row will be affected, change it ... highlighting changes automatically
//find the song at the new time 
//set c_time and n_time data
//if the current row has changed, then change highlighting
