/* TreeSize for Unix  http://treesize.sf.net/
 * Copyright (c) 2006-2007 Marcos Diez <marcos_AT_unitron.com.br>
 *
 * 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, see <http://www.gnu.org/licenses/>.
 */

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <pthread.h>

#include "FAfolderAnalyzer.h"
#include "TStreeSizeGui.h"
#include "support.h"

struct threadParameter{
  GtkWidget *treeView;
  char *folderName;
  char absoluteDirName[MAX_DIR_NAME];
};



int TSrunning=0;

#define MAX_FILE_SIZE 20
char fileSize[ MAX_FILE_SIZE ];

static char *printFileSize( double size ){
  char sizes[]="bkMGT"; 
  int i=0;
  while( size > 1024 && i < sizeof(sizes)){
    size/=1024.;
    i++;
  }
  snprintf( fileSize , MAX_FILE_SIZE , "%.2f%c" , size , sizes[i] );
  return fileSize;
}

static char* getFolderIcon( FolderInfo theFolder ){
  /*
    http://developer.gnome.org/doc/API/2.0/gtk/gtk-Stock-Items.html#GTK-STOCK-ABOUT:CAPS
  */
  if( ! FIisFolderAccessible( theFolder )) return GTK_STOCK_CANCEL;
  if( FIisFileFolder( theFolder ) ) return GTK_STOCK_FILE;
  if( FIisMountPoint( theFolder) ) return GTK_STOCK_HARDDISK;
  return GTK_STOCK_OPEN;
}

static void addColumns( GtkWidget *treeView )
{
  GtkTreeViewColumn   *col;
  GtkCellRenderer     *renderer;

  /* --- Column #1 --- */
  col = gtk_tree_view_column_new();
/*   gtk_tree_view_column_set_title(col, "Data Column"); */

  /* pack tree view column into tree view */
  gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), col);

  
  /* usage porcentage */
  renderer= gtk_cell_renderer_progress_new();
  gtk_tree_view_column_pack_start( col , renderer , FALSE );
  gtk_tree_view_column_set_attributes( col , renderer ,
				       "value" , COL_PORCENT , NULL );
  
  /* drive/folder/files/no access  */
  renderer = gtk_cell_renderer_pixbuf_new();
  gtk_tree_view_column_pack_start( col , renderer , FALSE );
  gtk_tree_view_column_set_attributes( col , renderer ,
				       "icon_name" , COL_ICON , NULL );
 
  /* folder usage size */
  renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start( col , renderer , TRUE );
  gtk_tree_view_column_set_attributes( col , renderer ,
				       "text" , COL_SIZE , NULL );

  /* folder name */
  renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start( col , renderer , TRUE );
  gtk_tree_view_column_set_attributes( col , renderer ,
				       "text" , COL_NAME , NULL );

  {

    GtkTreeSelection *select;
    select = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeView));
    gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
    /* future... */
/*     g_signal_connect (G_OBJECT (select), "changed", */
/* 		      G_CALLBACK (tree_selection_changed_cb), */
/* 		      NULL); */
  }
}


char *getFolderName( FolderInfo theFolder ){
  char *name = FIgetName( theFolder );
  if( FIisMountPoint( theFolder )){
    int size=strlen( name );
    char *newName;
    vecMalloc( newName , size + 30 );
    snprintf( newName ,  size + 30 , "%s [Free: %s]" , name , printFileSize( FIgetFreeSpace( theFolder ) ) );
    return newName;
  }
  else return name;
}

static GtkTreeModel *
fillTree( GtkTreeStore *treeStore ,
	  GtkTreeIter  *myTreeIter ,
	  GtkTreeIter  *parentTreeIter ,
	  FolderInfo theFolder ){

  FolderInfo *subFolders = FIgetSubFolders( theFolder );

  gtk_tree_store_append(treeStore, myTreeIter , parentTreeIter );

  gtk_tree_store_set(treeStore, myTreeIter,
		     COL_PORCENT , (guint)  FIgetPhysicalPorcent( theFolder)  ,
		     COL_ICON , getFolderIcon( theFolder ) , 
		     COL_SIZE,  printFileSize( FIgetPhysicalSize( theFolder ) ) ,
		     COL_NAME,  g_filename_display_name( getFolderName( theFolder ) ) , 
		     COL_PATH,  FIgetPath( theFolder ) ,
                     -1);

/*   FIprint( theFolder ); */
  if( subFolders ){
    GtkTreeIter  childTreeIter;

    while( *subFolders ){
      fillTree( treeStore, &childTreeIter , myTreeIter , *subFolders );
      subFolders++;
    }
  }
  return GTK_TREE_MODEL (treeStore);
}


static GtkTreeModel *
create_and_fill_model ( char *folder , bool onlyOneFileSystem )
{
  GtkTreeStore  *treeStore;
  GtkTreeIter    toplevel;

  FolderInfo     theFolder = FAanalyze( folder , onlyOneFileSystem );

  if( !TSrunning ){
    FIfree( theFolder );
    return 0;
  }
  
  treeStore = gtk_tree_store_new(NUM_COLS,
				 G_TYPE_INT   ,	   /* COL_PORCENT */
				 G_TYPE_STRING ,  /* COL_ICON */
				 G_TYPE_STRING ,  /* COL_SIZE */
				 G_TYPE_STRING ,  /* COL_NAME */
				 G_TYPE_STRING ); /* COL_PATH */

  
  fillTree( treeStore , &toplevel , 0 , theFolder  );
  FIfree( theFolder );
  return GTK_TREE_MODEL (treeStore);
}


void TSprepareTreeView( GtkWidget *treeView ){
  GtkWidget *entFolder= (GtkWidget *) lookup_widget( treeView , "entFolder");
  addColumns( treeView );
  gtk_widget_grab_focus( entFolder );
}


static pthread_t pt_id;
static struct threadParameter p;

static pthread_mutex_t mutexCalcSize = PTHREAD_MUTEX_INITIALIZER;

static void TScalculateSizeTread( struct threadParameter *data){
  GtkWidget *treeView = data->treeView;
  //char *folderName    = data->folderName;
  char *absoluteDirName = data->absoluteDirName;

  GtkTreeModel        *treeStoreModel;
  GtkWidget           *btnReload  = (GtkWidget *) lookup_widget( treeView , "btnReload"  );
  GtkWidget           *btnCancel  = (GtkWidget *) lookup_widget( treeView , "btnCancel"  );
  GtkWidget           *btnOnlyOneFileSystem  = (GtkWidget *) lookup_widget( treeView , "btnOnlyOneFileSystem"  );
  GtkWindow           *mainWindow = (GtkWindow *) lookup_widget( treeView , "mainWindow" );

  char newTitle[MAX_DIR_NAME + 15];


  pthread_mutex_lock(&mutexCalcSize);
  TSrunning=1;

  /* permanant UI changes */
  snprintf( newTitle , sizeof( newTitle ) , "%s - TreeSize for Unix" , absoluteDirName );
  gtk_entry_set_text              ( (GtkEntry *) lookup_widget( treeView , "entFolder" ) , (const gchar * ) absoluteDirName );

  { 				/* UI before TreeSize() */
    gtk_window_set_title (GTK_WINDOW (mainWindow),  newTitle );

    gtk_widget_set_sensitive (btnReload, FALSE );
    gtk_widget_set_sensitive (btnOnlyOneFileSystem, FALSE );
    gtk_widget_set_sensitive (btnCancel, TRUE );
    
    {
      GdkCursor *cursor;
      cursor = gdk_cursor_new( GDK_WATCH );
      gdk_window_set_cursor( treeView->window , cursor );
      gdk_cursor_unref (cursor);
    }
    
  }


  /* the job itself */
  gboolean onlyOneFileSystem =
    gtk_toggle_tool_button_get_active( (GtkToggleToolButton *) btnOnlyOneFileSystem );

  treeStoreModel = create_and_fill_model( absoluteDirName  , onlyOneFileSystem );

  { /* UI after treeSize() */
    GdkCursor *cursor;
    cursor = gdk_cursor_new( GDK_LEFT_PTR );
    gdk_window_set_cursor( treeView->window , cursor );
    gdk_cursor_unref (cursor);
    
    gtk_widget_set_sensitive (btnCancel, FALSE);
    gtk_widget_set_sensitive (btnReload, TRUE);
    gtk_widget_set_sensitive (btnOnlyOneFileSystem, TRUE );

  }

  if( !TSrunning ){		/* were we aborted ? */
    gtk_widget_set_sensitive (btnCancel, FALSE);
    pthread_mutex_unlock(&mutexCalcSize);
    return;
  }
  
  gtk_tree_view_set_model(GTK_TREE_VIEW( treeView ), treeStoreModel);

  
  /* /\\*   gtk_list_store_clear ( treeStoreModel ); *\\/ */
  g_object_unref(treeStoreModel); /* destroy model automatically with view */
  TSrunning=0;
  pthread_mutex_unlock(&mutexCalcSize);
}/*  */


void TScalculateSize( GtkWidget *treeView , char *folderName ){

  if( !FAgetFolderAbsoluteName( folderName , p.absoluteDirName , 0  , 1 ) ){
    GtkWindow           *mainWindow = (GtkWindow *) lookup_widget( treeView , "mainWindow" );
    GtkWidget *dialog = gtk_message_dialog_new ( mainWindow ,
						GTK_DIALOG_DESTROY_WITH_PARENT,
						GTK_MESSAGE_ERROR,
						GTK_BUTTONS_CLOSE,
						"Invalid Folder '%s'",
						folderName );
    gtk_dialog_run (GTK_DIALOG (dialog));
    gtk_widget_destroy (dialog);
    return;
  }
  p.treeView=treeView;
  p.folderName=folderName;
  /* here I start the new Thread */

  pthread_create( &pt_id , 0 ,  (void *)(void *) TScalculateSizeTread  ,  &p );

}
