/* GAdmin-Rsync - An easy to use GTK+ frontend for the rsync backup client and server.
 * Copyright (C) 2007-2011 Magnus Loef <magnus-swe@telia.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 3 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
*/



#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "widgets.h"
#include "gettext.h"
#include "allocate.h"
#include "show_log.h"
#include "show_info.h"
#include "cron_functions.h"

#define EXPAND_LOG 1

extern gchar *global_backup_name;



void delete_log(struct w *widgets)
{
    /* Clear the log and extended log files for the selected backup */
    FILE *fp;
    gchar *log_path; 

    log_path = mk_log_path(global_backup_name);
    if( log_path == NULL || strlen(log_path) < 10 )
    {
        printf("clear_log: log path too short\n");
        if( log_path!=NULL )
          g_free(log_path);
	return;
    }
    if((fp=fopen(log_path, "w+"))==NULL)
    {
        if( log_path!=NULL )
          g_free(log_path);
	return;
    }
    fclose(fp);

    if( log_path!=NULL )
      g_free(log_path);

    log_path = mk_extended_log_path(global_backup_name);
    if( log_path == NULL || strlen(log_path) < 10 )
    {
       printf("clear_log: extended log path too short\n");
       return;
    }
    if((fp=fopen(log_path, "w+"))==NULL)
    {
        if( log_path!=NULL )
          g_free(log_path);
	return;
    }
    fclose(fp);

    if( log_path!=NULL )
      g_free(log_path);

    populate_log(widgets);
}


void populate_log(struct w *widgets)
{
    FILE *fp;
    long file_size = 0;
    char *line, *val;
    long i = 0, begin = 0;
    GtkTreeIter iter;
    gchar *log_path, *info, *utf8;

    /* Create a log path for the selected backup */
    log_path = mk_log_path(global_backup_name);
    if( log_path == NULL || strlen(log_path) < 10 )
    {
	info = g_strdup_printf("Can not read the selected backups logfile. Filename too short.\n");
	show_info(info);
	g_free(info);

	if( log_path!=NULL )       
          g_free(log_path);

        /* Destroy the backup log window and return */
        gtk_widget_destroy(widgets->log_window);
        return;
    }


    /* Clear the log treeview */
    gtk_list_store_clear(GTK_LIST_STORE(widgets->log_store));


    /* Show the selected backup log in the treeview */
    if((fp=fopen(log_path, "r"))==NULL)
    {
        info = g_strdup_printf("Can not read the selected backups logfile.\nThe backup needs to run first so a log is created.\n");
	show_info(info);
	g_free(info);

	if( log_path!=NULL )       
          g_free(log_path);
        
        /* Destroy the backup log window and return */
        gtk_widget_destroy(widgets->log_window);
        return;
    }
    fseek(fp, 0, SEEK_END);
    file_size = ftell(fp);
    rewind(fp);
                                            
    line = allocate(file_size+1);
    val  = allocate(file_size+1);
                                                        
    if( file_size > 1 )
    while(fgets(line, file_size, fp)!=NULL)
    {                                 
	if( strlen(line) < 10  )
	  continue;

	gtk_list_store_append(GTK_LIST_STORE(widgets->log_store), &iter);

	/* Insert start date and time */
	sscanf(line, "%s", val);
	for(i=0; val[i]!='\0'; i++)
	{
	    /* Change underscore to a space */
	    if( val[i]=='_' )
	      val[i]=' ';
	}
	utf8 = g_locale_to_utf8(val, strlen(val), NULL, NULL, NULL);
	if( utf8!=NULL )
	{
	    gtk_list_store_set(widgets->log_store, &iter, 0, utf8, -1);
	    g_free(utf8);
	}

	/* Insert finish date and time */
	sscanf(line, "%*s %s", val);
	for(i=0; val[i]!='\0'; i++)
	{
	    /* Change underscore to a space */
	    if( val[i]=='_' )
	      val[i]=' ';
	}
	utf8 = g_locale_to_utf8(val, strlen(val), NULL, NULL, NULL);
	if( utf8!=NULL )
	{
	    gtk_list_store_set(widgets->log_store, &iter, 1, utf8, -1);
	    g_free(utf8);
	}

	/* Insert success / failure state */
	sscanf(line, "%*s %*s %*s %s", val);
	if( strstr(line, "success") )
	  utf8 = g_locale_to_utf8("Success", -1, NULL, NULL, NULL);
	else
	  utf8 = g_locale_to_utf8("Failure", -1, NULL, NULL, NULL);
	
	if( utf8!=NULL )
	{
	    gtk_list_store_set(widgets->log_store, &iter, 2, utf8, -1);
	    g_free(utf8);
	}

	/* Insert source */
	for(i=0; line[i]!='\0'; i++)
	{
	    if( line[i]=='[' )
	      break;
	}
	begin = i+1;

	for(i=i; line[i]!='\0'; i++)
	{
	    if( line[i]==']' )
	      break;
	}
	i++;

	snprintf(val, i-begin, "%s", &line[begin]);
	utf8 = g_locale_to_utf8(val, strlen(val), NULL, NULL, NULL);
	if( utf8!=NULL )
	{
	    gtk_list_store_set(widgets->log_store, &iter, 3, utf8, -1);
	    g_free(utf8);
	}

	/* Insert destination */
	for(i=i; line[i]!='\0'; i++)
	{
	    if( line[i]=='[' )
	    {
		begin = i;
		break;
	    }
	}
	begin = i+1;

	for(i=i; line[i]!='\0'; i++)
	{
	    if( line[i]==']' )
	    {
		line[i]='\0';
	        break;
	    }
	}
	i++;
	
	snprintf(val, i-begin, "%s", &line[begin]);
	utf8 = g_locale_to_utf8(val, strlen(val), NULL, NULL, NULL);
	if( utf8!=NULL )
	{
	    gtk_list_store_set(widgets->log_store, &iter, 4, utf8, -1);
	    g_free(utf8);
	}
    }
    fclose(fp);

    if( log_path!=NULL )
    g_free(log_path);

    free(line);
    free(val);
}


/* Create and show the log window */
void show_log_window(struct w *widgets)
{
    GtkWidget *vbox;
    GtkWidget *scrolled_window;
    GtkCellRenderer *cell;
    GtkTreeViewColumn *col[5];
    GtkWidget *hbuttonbox;
    GtkTooltips *tooltips;
    gchar *info;
    int colnr = 0;    

    tooltips = gtk_tooltips_new();

    /* Create the log window */
    widgets->log_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_size_request(widgets->log_window, 630, 350);
    gtk_window_set_position(GTK_WINDOW(widgets->log_window), GTK_WIN_POS_CENTER);
  
    /* Set window information */
    info = g_strdup_printf(_("GAdmin-Rsync %s \t %s"), VERSION, global_backup_name);
    gtk_window_set_title(GTK_WINDOW(widgets->log_window), info);
    g_free(info);

    /* Create the scrolled window */
    vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(widgets->log_window), vbox);

    scrolled_window = gtk_scrolled_window_new(NULL, NULL);
    gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);

    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), 
						    GTK_POLICY_AUTOMATIC, 
						    GTK_POLICY_ALWAYS);
    /* Must set a larger size or it wont scroll */
    gtk_widget_set_size_request(scrolled_window, -1, 100);


    /* 7 columns (Date, State, Src, Dst) */
    widgets->log_store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
    
    widgets->log_treeview = gtk_tree_view_new();
    gtk_tree_view_set_model(GTK_TREE_VIEW(widgets->log_treeview), GTK_TREE_MODEL(widgets->log_store));

    gtk_container_add(GTK_CONTAINER(scrolled_window), widgets->log_treeview);
    gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(widgets->log_treeview), TRUE);


    cell = gtk_cell_renderer_text_new();

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Started"), cell, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->log_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Ended"), cell, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->log_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Status"), cell, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->log_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Source"), cell, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->log_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Destination"), cell, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->log_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    /* Create a hbutton box to hold the buttons */
    hbuttonbox = gtk_hbutton_box_new();
    gtk_box_pack_start(GTK_BOX(vbox), hbuttonbox, FALSE, FALSE, 0);
    gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox), GTK_BUTTONBOX_SPREAD);
            

    /* Fixme: Use custom text "Clear log". The clear log button */
    GtkWidget *delete_log_button = gtk_button_new_from_stock(GTK_STOCK_DELETE);
    gtk_box_pack_start(GTK_BOX(hbuttonbox), delete_log_button, FALSE, TRUE, 0);

    /* The clear log button signal */
    g_signal_connect_swapped(delete_log_button, "clicked",
                           G_CALLBACK(delete_log), widgets);



    GtkWidget *extended_log_button = gtk_button_new();
    gtk_tooltips_set_tip(tooltips, extended_log_button, _("Show extended log"), NULL);
    GtkWidget *alignment2 = gtk_alignment_new(0.5, 0.5, 0, 0);
    gtk_container_add(GTK_CONTAINER(extended_log_button), alignment2);
    GtkWidget *hbox2 = gtk_hbox_new(FALSE, 2);
    gtk_container_add(GTK_CONTAINER(alignment2), hbox2);
    GtkWidget *image2 = gtk_image_new_from_stock("gtk-find", GTK_ICON_SIZE_BUTTON);
    gtk_box_pack_start(GTK_BOX(hbox2), image2, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbuttonbox), extended_log_button, FALSE, TRUE, 0);
    GtkWidget *label2 = gtk_label_new_with_mnemonic(_("Show extended log"));
    gtk_box_pack_start(GTK_BOX(hbox2), label2, FALSE, FALSE, 0);
    gtk_label_set_justify(GTK_LABEL(label2), GTK_JUSTIFY_LEFT);
            
    /* Show extended log button signal */
    g_signal_connect_swapped(extended_log_button, "clicked",
                           G_CALLBACK(show_extended_log_window), widgets);


    /* Close log window button */
    GtkWidget *close_log_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
    gtk_box_pack_start(GTK_BOX(hbuttonbox), close_log_button, FALSE, TRUE, 0);

    /* The window close button signals */
    g_signal_connect_swapped((gpointer) close_log_button, "clicked",
              G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(widgets->log_window));

    g_signal_connect(GTK_WINDOW(widgets->log_window), "delete_event", 
		        G_CALLBACK(gtk_widget_destroy), NULL);

    gtk_widget_show_all(widgets->log_window);

    /* Populate the textview */
    populate_log(widgets);
}


/* Create and show the extended log window */
void show_extended_log_window(struct w *widgets)
{
    GtkWidget *vbox;
    GtkWidget *scrolled_window;
    GtkCellRenderer *cell;
    GtkTreeViewColumn *col[4];
    GtkWidget *hbuttonbox;
    GtkTooltips *tooltips;
    gchar *info;
    int colnr = 0;    

    tooltips = gtk_tooltips_new();

    /* Create the extended log window */
    widgets->extended_log_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_size_request(widgets->extended_log_window, 630, 350);
    gtk_window_set_position(GTK_WINDOW(widgets->extended_log_window), GTK_WIN_POS_CENTER);
  
    /* Set window information */
    info = g_strdup_printf(_("GAdmin-Rsync %s \t %s"), VERSION, global_backup_name);
    gtk_window_set_title(GTK_WINDOW(widgets->extended_log_window), info);
    g_free(info);

    /* Create the scrolled window */
    vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(widgets->extended_log_window), vbox);

    scrolled_window = gtk_scrolled_window_new(NULL, NULL);
    gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);

    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), 
						    GTK_POLICY_AUTOMATIC, 
						    GTK_POLICY_ALWAYS);
    /* Must set a larger size or it wont scroll */
    gtk_widget_set_size_request(scrolled_window, -1, 100);

    widgets->extended_log_store = gtk_list_store_new(1, G_TYPE_STRING);
    
    widgets->extended_log_treeview = gtk_tree_view_new();
    gtk_tree_view_set_model(GTK_TREE_VIEW(widgets->extended_log_treeview), GTK_TREE_MODEL(widgets->extended_log_store));

    gtk_container_add(GTK_CONTAINER(scrolled_window), widgets->extended_log_treeview);
    gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(widgets->extended_log_treeview), TRUE);


    cell = gtk_cell_renderer_text_new();

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Extended backup log"), cell, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->extended_log_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    /* Create a hbutton box to hold the button */
    hbuttonbox = gtk_hbutton_box_new();
    gtk_box_pack_start(GTK_BOX(vbox), hbuttonbox, FALSE, FALSE, 0);
    gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox), GTK_BUTTONBOX_SPREAD);

    /* Close extended log window button */
    GtkWidget *close_log_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
    gtk_box_pack_start(GTK_BOX(hbuttonbox), close_log_button, FALSE, TRUE, 0);

    /* The window close button signals */
    g_signal_connect_swapped((gpointer) close_log_button, "clicked",
              G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(widgets->extended_log_window));

    g_signal_connect(GTK_WINDOW(widgets->extended_log_window), "delete_event", 
		        G_CALLBACK(gtk_widget_destroy), NULL);

    gtk_widget_show_all(widgets->extended_log_window);

    /* Populate the textview */
    populate_extended_log(widgets);
}


void populate_extended_log(struct w *widgets)
{
    FILE *fp;
    long file_size = 0;
    char *line;
    long i = 0;
    GtkTreeIter iter;
    gchar *extended_log_path, *info, *utf8;

    /* Create a log path for the selected backup */
    extended_log_path = mk_extended_log_path(global_backup_name);
    if( extended_log_path == NULL || strlen(extended_log_path) < 10 )
    {
	info = g_strdup_printf("Can not read the selected backups extended logfile. Filename too short.\n");
	show_info(info);
	g_free(info);
       
        g_free(extended_log_path);

        /* Destroy the backup log window and return */
        gtk_widget_destroy(widgets->extended_log_window);
        return;
    }

    /* Clear the log treeview */
    gtk_list_store_clear(GTK_LIST_STORE(widgets->extended_log_store));


    /* Show the extended backup log in the treeview */
    if((fp=fopen(extended_log_path, "r"))==NULL)
    {
        info = g_strdup_printf("Can not read the selected backups extended logfile.\n");
	show_info(info);
	g_free(info);

        g_free(extended_log_path);
        
        /* Destroy the backup log window and return */
        gtk_widget_destroy(widgets->extended_log_window);
        return;
    }
    fseek(fp, 0, SEEK_END);
    file_size = ftell(fp);
    rewind(fp);
                                            
    line = allocate(file_size+1);
                                                        
    if( file_size > 1 )
    while(fgets(line, file_size, fp)!=NULL)
    {                                 
	if( strlen(line) < 10 || strlen(line) > 20000 )
	  continue;

	for(i=0; line[i]!='\0'; i++)
	if( line[i]=='\n' )
	{    
	    line[i]='\0';
	    break;
	}

	gtk_list_store_append(GTK_LIST_STORE(widgets->extended_log_store), &iter);

	utf8 = g_locale_to_utf8(line, strlen(line), NULL, NULL, NULL);
	if( utf8!=NULL )
	{
	    gtk_list_store_set(widgets->extended_log_store, &iter, 0, utf8, -1);
	    g_free(utf8);
	}
    }
    fclose(fp);
    g_free(extended_log_path);

    free(line);
}
