/*
 * Initial main.c file generated by Glade. Edit as required.
 * Glade will not overwrite this file.
 */

#include "../core/HandBrake.h"

#include <gtk/gtk.h>

#include "interface.h"
#include "support.h"

#include "status.h"

#define GLADE_HOOKUP_OBJECT(component,widget,name) \
  g_object_set_data_full (G_OBJECT (component), name, \
    gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)

GtkWidget *hb_win_main = NULL;
HBHandle  *hb_handle = NULL;
HBStatus  *hb_status = NULL;

static int HBMain( void *data );

/* libhb callbacks */
static void Scanning( void * data, int title, int titleCount );
static void ScanDone( void * data, HBList * titleList );
static void Encoding( void * data, float position, int pass,
                      int passCount, float frameRate,
                      float avgFrameRate, int remainingTime );
static void RipDone( void * data, int result );


int main (int argc, char **argv )
{
    HBCallbacks callbacks;
    GtkWidget   *widget;
    GList       *items = NULL;

    int i_dummy;

    /* Create HB stuff */
    if( ( hb_handle = HBInit( 1, 0 ) ) == NULL )
    {
        g_print( "HBInit: failed\n" );
        return -1;
    }

    /* Emulate a HBStatus */
    hb_status = malloc( sizeof( HBStatus ) );
    hb_status->i_state = HB_STATE_NEED_DEVICE;
    hb_status->b_new = 1;
    hb_status->i_title = 0;
    hb_status->i_title_count = 0;
    hb_status->titleList = NULL;
    hb_status->position = 0.0;
    hb_status->i_remaining = 0;
    hb_status->fps = 0.0;

    /* Set libhb callbacks */
    callbacks.data     = NULL;
    callbacks.scanning = Scanning;
    callbacks.scanDone = ScanDone;
    callbacks.encoding = Encoding;
    callbacks.ripDone  = RipDone;
    HBSetCallbacks( hb_handle, callbacks );

    gtk_set_locale ();
    gtk_init (&argc, &argv);

    //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");

    /* Create the main window */
    hb_win_main = create_win_main();
    gtk_window_set_title( GTK_WINDOW(hb_win_main), "HandBrake " HB_VERSION );

    widget = lookup_widget( hb_win_main, "combo1" );
    gtk_combo_disable_activate( GTK_COMBO( widget ) );

    widget = lookup_widget( hb_win_main, "combo2" );
    gtk_combo_disable_activate( GTK_COMBO( widget ) );

    widget = lookup_widget( hb_win_main, "optionmenu_bitrate" );
    gtk_option_menu_set_history( GTK_OPTION_MENU(widget), 2 );

    /* build dvd list */
    items = g_list_append (items, "" );
    items = g_list_append (items, "/dev/dvd" );
    gtk_combo_set_popdown_strings( GTK_COMBO(lookup_widget( hb_win_main, "combo1") ), items );

    /* Display the main window */
    gtk_widget_show( hb_win_main );

    i_dummy = gtk_timeout_add( 100, (GtkFunction)HBMain, NULL );
    gtk_main();
    gtk_timeout_remove( i_dummy );

    return 0;
}

static void StatusBarUpdate( char *msg )
{
    GtkWidget *widget = lookup_widget( hb_win_main, "statusbar" );

    gtk_statusbar_push( GTK_STATUSBAR(widget),
                        gtk_statusbar_get_context_id(GTK_STATUSBAR(widget), "status" ),
                        msg );
}

static void DisplayError( char *title, char *msg )
{
    GtkWidget *dialog = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL,
                                                GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
                                                "<b>%s</b>\n\n%s", title, msg );
    gtk_label_set_use_markup( GTK_LABEL( GTK_MESSAGE_DIALOG(dialog)->label), TRUE );
    gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK );
    gtk_window_set_modal( GTK_WINDOW(dialog), TRUE );
    gtk_dialog_run( GTK_DIALOG(dialog) );
    gtk_widget_destroy( dialog );
}

static void DisplayInfo( char *msg )
{
    GtkWidget *dialog = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL,
                                                GTK_MESSAGE_INFO, GTK_BUTTONS_OK, msg );
    gtk_label_set_use_markup( GTK_LABEL( GTK_MESSAGE_DIALOG(dialog)->label), TRUE );
    gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK );
    gtk_window_set_modal( GTK_WINDOW(dialog), TRUE );
    gtk_dialog_run( GTK_DIALOG(dialog) );
    gtk_widget_destroy( dialog );
}

static int HBMain( void *data )
{
    int        b_new = hb_status->b_new;
    GtkWidget  *widget;
    gchar      msg[1000];

    hb_status->b_new = 0;

    switch( hb_status->i_state )
    {
        case HB_STATE_NEED_DEVICE:
            if( b_new )
            {
                g_print( "HBMain: HB_MODE_NEED_DEVICE\n" );
                gtk_widget_set_sensitive( lookup_widget( hb_win_main, "frame_dvd"), TRUE );
                StatusBarUpdate( "Enter a device" );
            }
            break;

        case HB_STATE_SCANNING:
            if( b_new )
            {
                g_print( "HBMain: HB_MODE_SCANNING\n" );
            }

            gtk_widget_set_sensitive( lookup_widget( hb_win_main, "frame_dvd"), FALSE );

            gtk_progress_bar_pulse( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" ) ));
            if( hb_status->i_title )
            {
                sprintf( msg, "Scanning title %d/%d...", hb_status->i_title, hb_status->i_title_count );
            }
            else
            {
                sprintf( msg, "Opening device..." );
            }
            StatusBarUpdate( msg );
            break;

        case HB_STATE_INVALID_DEVICE:
            if( b_new )
            {
                g_print( "HBMain: HB_MODE_INVALID_DEVICE\n" );

                gtk_widget_set_sensitive( lookup_widget( hb_win_main, "frame_dvd"), TRUE );

                gtk_entry_set_text( GTK_ENTRY(lookup_widget( hb_win_main, "entry_device")), "" );

                gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), 0.0 );

                StatusBarUpdate( "Enter a valid device" );

                /* error dialog */
                DisplayError( "Invalid device", "Please select a valide device" );
            }
            break;

        case HB_STATE_READY_TO_RIP:
            if( b_new )
            {
                GtkWidget *optionmenu_title = lookup_widget( hb_win_main, "optionmenu_title" );
                GtkWidget *menu;
                GtkWidget *item;
                int i;

                g_print( "HBMain: HB_MODE_READY_TO_RIP\n" );

                /* create title menu */
                menu = gtk_menu_new();
                for( i = 0; i < HBListCount( hb_status->titleList ); i++ )
                {
                    HBTitle *title = (HBTitle*) HBListItemAt( hb_status->titleList, i );
                    char string[1024];

                    sprintf( string, "%d - %02dh%02dm%02ds",
                             title->title, title->hours, title->minutes,
                             title->seconds );

                    item = gtk_menu_item_new_with_mnemonic( string );
                    gtk_widget_show( item );
                    gtk_menu_shell_append( GTK_MENU_SHELL(menu), item );
                }

                gtk_option_menu_set_menu( GTK_OPTION_MENU(optionmenu_title), menu );
                GLADE_HOOKUP_OBJECT( hb_win_main, menu, "menu_title" );

                /* unhide */
                widget = lookup_widget( hb_win_main, "vbox_parameters" );
                gtk_widget_show( widget );

                gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), 0.0 );
                gtk_progress_bar_set_text( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), "" );

                StatusBarUpdate( "Select your parameters" );
            }
            break;

        case HB_STATE_ENCODING:
            if( b_new )
            {
                /* change the name to Stop */
                widget = lookup_widget( hb_win_main, "button_start_label" );
                gtk_label_set_text( GTK_LABEL( widget ), "Stop" );

                widget = lookup_widget( hb_win_main, "button_start_image" );
                gtk_image_set_from_stock( GTK_IMAGE(widget), "gtk-cancel", GTK_ICON_SIZE_BUTTON );

                gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_video"), FALSE );
                gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_audio"), FALSE );
                gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_output"), FALSE );
            }

            if( hb_status->position <= 0 )
            {
                StatusBarUpdate( "Starting..." );
            }
            else
            {
                char string[1024];

                /* Status bar */
                sprintf( string, "Encoding: %02dh%02dm%02ds remaining",
                         hb_status->i_remaining / 3600,
                         ( hb_status->i_remaining % 3600 ) / 60,
                         hb_status->i_remaining % 60 );
                StatusBarUpdate( string );

                /* Progressbar */
                sprintf( string, "%.2f %% (%.2f fps)", 100 * hb_status->position, hb_status->fps );
                gtk_progress_bar_set_text( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), string );
                gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), hb_status->position );
            }
            break;

        case HB_STATE_DONE:
        case HB_STATE_CANCELED:
            if( b_new )
            {
                g_print( "HBMain: HB_MODE_DONE/HB_MODE_CANCELED\n" );

                /* change the name to Start */
                widget = lookup_widget( hb_win_main, "button_start_label" );
                gtk_label_set_text( GTK_LABEL( widget ), "Start" );

                widget = lookup_widget( hb_win_main, "button_start_image" );
                gtk_image_set_from_stock( GTK_IMAGE(widget), "gtk-apply", GTK_ICON_SIZE_BUTTON );

                gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), 0.0 );
                gtk_progress_bar_set_text( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), "" );

                if( hb_status->i_state == HB_STATE_DONE )
                {
                    StatusBarUpdate( "Done." );
                    DisplayInfo( "Encoding finished with success." );
                }
                else
                {
                    StatusBarUpdate( "Canceled." );
                    DisplayInfo("Encoding canceled.");
                }

                gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_video"), TRUE );
                gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_audio"), TRUE );
                gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_output"), TRUE );
            }
            break;

        case HB_STATE_ERROR:
            if( b_new )
            {
                char *msg = "Unknown";

                g_print( "HBMain: HB_MODE_ERROR\n" );

                /* change the name to Start */
                widget = lookup_widget( hb_win_main, "button_start_label" );
                gtk_label_set_text( GTK_LABEL( widget ), "Start" );

                widget = lookup_widget( hb_win_main, "button_start_image" );
                gtk_image_set_from_stock( GTK_IMAGE(widget), "gtk-apply", GTK_ICON_SIZE_BUTTON );

                gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), 0.0 );
                gtk_progress_bar_set_text( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), "" );

                StatusBarUpdate( "Error." );
                switch( hb_status->i_error )
                {
#if 0
                    case HB_ERROR_A52_SYNC:
                        msg = "corrupted AC3 data.";
                        break;
                    case HB_ERROR_AVI_WRITE:
                        msg = "could not write to file.";
                        break;
                    case HB_ERROR_DVD_OPEN:
                        msg = "could not open device.";
                        break;
                    case HB_ERROR_DVD_READ:
                        msg = "DVD read failed.";
                        break;
                    case HB_ERROR_MP3_INIT:
                        msg = "could not init MP3 encoder.";
                        break;
                    case HB_ERROR_MP3_ENCODE:
                        msg = "MP3 encoder failed.";
                        break;
                    case HB_ERROR_MPEG4_INIT:
                        msg = "could not init MPEG4 encoder.";
                        break;
#endif
                    default:
                        msg = "Generic error";
                        break;
                }
                DisplayError( "An error occured", msg );

                gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_video"), TRUE );
                gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_audio"), TRUE );
                gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_output"), TRUE );
            }
            break;
    }


    return TRUE;
}


static void Scanning( void * data, int title, int titleCount )
{
    if( hb_status->i_state != HB_STATE_SCANNING )
    {
        hb_status->i_state = HB_STATE_SCANNING;
        hb_status->b_new = 1;
    }
    hb_status->i_title = title;
    hb_status->i_title_count = titleCount;
}

static void ScanDone( void * data, HBList * titleList )
{
    if( titleList == NULL )
    {
        hb_status->i_state = HB_STATE_INVALID_DEVICE;
    }
    else
    {
        hb_status->i_state = HB_STATE_READY_TO_RIP;
    }
    hb_status->b_new = 1;

    hb_status->titleList = titleList;
}

static void Encoding( void * data, float position, int pass,
                      int passCount, float frameRate,
                      float avgFrameRate, int remainingTime )
{
    if( hb_status->i_state != HB_STATE_ENCODING )
    {
        hb_status->i_state = HB_STATE_ENCODING;
        hb_status->b_new = 1;
    }

    hb_status->position = position;
    hb_status->fps = frameRate;
    hb_status->i_remaining = remainingTime;
}

static void RipDone( void * data, int result )
{
    /* TODO check result */
    hb_status->i_state = HB_STATE_DONE;
    hb_status->b_new = 1;
}

