// My File Manager (MFM).
//
// Copyright 2005-2006 by Stefano Gatti.
//
// 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 2
// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
//=====================================================================

#include <locale.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <locale.h>
#include <malloc.h>
#include <stdlib.h>
#include <sys/stat.h>

#include <FL/fl_draw.H>
#include <FL/filename.H>

#include "mfm_dir_ui.hxx"
#include "mfm_dnd.hxx"
#include "mfm_get_path_ui.hxx"
#include "mfm_util.hxx"
#include "mfm_confirm_ui.hxx"
#include "file_info.hxx"


/**************************************************************************
* Methods of class_mfm_browser
****************************************************************************/

/**************************************************************************
* Constructor
****************************************************************************/

class_mfm_dir_browser::class_mfm_dir_browser(int x, int y, int w, int h, void *ptr) : Fl_Hold_Browser(x, y, w, h, NULL) {

  when(FL_WHEN_NOT_CHANGED);
  
  ptr_dir = ptr;


} // class_mfm_dir_browser::class_mfm_dir_browser


/**************************************************************************
*
* get_dir
*
* Return directory in passed row
*
****************************************************************************/

char *class_mfm_dir_browser::get_dir(int row) {

 char *path;
 
 if (row == 0)
 
   row = value();

 if (((class_mfm_open_dir *)data(row))->parent != NULL) 

   asprintf(&path, "%s%s/", ((class_mfm_open_dir *)((class_mfm_open_dir *)data(row))->parent)->path, text(row)+(((class_mfm_open_dir *)data(row))->level)*2); 
      
 else   

   asprintf(&path, "%s", text(row));   
   
 return path;  
         
} // class_mfm_dir_browser::get_dir


/**************************************************************************
*
* load_dir
*
* Load/unload in browser selected directory
*
****************************************************************************/

void class_mfm_dir_browser::load_dir(int row) {

  dirent  **files;

  file_info file_stat;  
  
  class_mfm_open_dir *open_dir;  
  
  char *path = NULL;

  if (row == 0) {

    clear();
    
    open_dir = new class_mfm_open_dir;    
    
    open_dir->path = NULL;          
    
    open_dir->parent = NULL;
    
    open_dir->level = 0;      
    
    add("/", open_dir); 

  }  
    
  else if (((class_mfm_open_dir *)data(row))->path == NULL) {

    path = get_dir(row);

    ((class_mfm_open_dir *)data(row))->path = path;

    int num_files = fl_filename_list(path, &files, fl_alphasort);

    if (num_files > 0) { 

      for (int i = num_files - 1; i >= 0; i--) {
  
        if (strncmp(files[i]->d_name, ".", 1) && strncmp(files[i]->d_name, "..", 2)     
            && strncmp(files[i]->d_name, "./", 2) && strncmp(files[i]->d_name, "../", 3))  {
              
          file_stat.set_file(path, files[i]->d_name);

          if (file_stat.is_dir())  {        
    
            int last_ch = strlen(files[i]->d_name);
 
            char *string,
                  format[8];            
        
            if ((files[i]->d_name)[last_ch-1] == '/')
        
              (files[i]->d_name)[last_ch-1] = 0;
              
            open_dir = new class_mfm_open_dir;                
              
            open_dir->path = NULL;          
    
            open_dir->parent = (class_mfm_open_dir *)data(row);   
            
            open_dir->level = ((class_mfm_open_dir *)(open_dir->parent))->level + 1;
            
            sprintf(format, "%%%is%%s", open_dir->level*2);
                 
            asprintf(&string, format, "", files[i]->d_name);            
  
            insert(row+1, string, open_dir);  
            
            free(string);

          }
    
        }

        free(files[i]);

      }
  
      free(files);
  
    }
    
  
  }
  
  else  {

    while (row < size() && ((class_mfm_open_dir *)data(row + 1))->level > ((class_mfm_open_dir *)data(row))->level)
    
      remove(row + 1);     

    free(((class_mfm_open_dir *)data(row))->path);
    
    ((class_mfm_open_dir *)data(row))->path = NULL;

  }       

} // class_mfm_dir_browser::load_dir


/*********************************************************************
*
* get_pointed_row
*
* Return the row pointed by mouse cursor
*
*********************************************************************/

int class_mfm_dir_browser::get_pointed_row() {

  int row = 0,
      xm = Fl::event_x(),
      ym = Fl::event_y();

  if (xm >= x() && xm < x()+w() &&
            ym >= y() && ym < y()+h()) {

    row = (ym - y() + position())/incr_height() + 1;

    if (row >= size())

      row = 0;

  }

  return row;

} // get_pointed_row


/**************************************************************************
* Handle function
****************************************************************************/

int class_mfm_dir_browser::handle(int event) {

  int ret = 0;
  
  char *stringa;

  Fl_Hold_Browser::handle(event);  

// button 1 double click

	if (event == FL_PUSH && Fl::event_button()==1 && Fl::event_clicks()) {

    load_dir(value());

    ret = 1;

    Fl::event_clicks(-1);       
        
  }                

  if (value() > 0 || event == FL_DND_RELEASE) {
    
  	switch (event) {
      
      case FL_RELEASE:
    
// button 2 released

        if (Fl::event_button()==2) {       
   
          new class_mfm_window(get_dir(0));

          ret = 1;
          
        }
        
// button 3 released

        else if (Fl::event_button()==3) {            

          ((class_mfm_dir *)ptr_dir)->mfm_dir_popup->position(Fl::event_x(), Fl::event_y());

          ((class_mfm_dir *)ptr_dir)->mfm_dir_popup->popup();
               
          ret = 1;
                
        }
      
        break;

      case FL_DRAG:
    
// button 2 drag

        if (Fl::event_button()==2) {
      
          asprintf(&stringa, "%s", get_dir(0));
      
          drag_source_ptr = this;
  
          drag_source = 3;      

          Fl::copy(stringa, strlen(stringa), 0);

          Fl::dnd();  

          ret = 1;
        
          free(stringa);

        }

// button 3 drag

        else if (Fl::event_button()==3) {

          asprintf(&stringa, "%s", get_dir(0));

          drag_source_ptr = this;
    
          drag_source = 2;
        
          Fl::copy(stringa, strlen(stringa), 0);

          Fl::dnd();  

          ret = 1;

        }
      
        break;
      
      case FL_DND_RELEASE:    

        drag_target_ptr = ptr_dir;
  
        drag_target = 2;       
    
        dnd_cb(); 
    
        break;    
        
    }   
    
  }  
  
  if (ret == 0)
  
    ret = Fl_Hold_Browser::handle(event);  
     
  return ret;
			         			
} // class_mfm_dir_browser::handle


/**************************************************************************
* Metodi di class_mfm_dir
****************************************************************************/

/**************************************************************************
* Constructor
****************************************************************************/

class_mfm_dir::class_mfm_dir() : class_mfm_dir_fluid() {

//FILE   *stream = NULL;
//char   *config_file = NULL;

  mfm_dir_browser = new class_mfm_dir_browser(mfm_dir_browser_group->x(), mfm_dir_browser_group->y(), mfm_dir_browser_group->w(), mfm_dir_browser_group->h(), this);

  mfm_dir->add(mfm_dir_browser);
  
  mfm_dir_browser->load_dir(0);
 
  mfm_dir_browser->load_dir(1);
  
  popup = mfm_popup_dir_menu;

/* Not fully developed, commenting out:

  asprintf(&config_file, "%s/.mfm/mfm-def.cfg", HOMEDIR); 

  if ((stream = fopen (config_file,"r"))!=NULL) {
  
    char *stringa = NULL,
         command[21];

    int  num, value;

    size_t dim;
  
    while (getline(&stringa, &dim, stream)>0) {

      num = sscanf(stringa, "%20s %i", command, &value);
      
      if (strcmp(command, "mode_verbose") == 0)      
      
        verbose = value;
              
      else if (strcmp(command, "mode_overwrite") == 0)      
      
        overwrite = value;                                        
                           
    }

    fclose(stream);
    
    free(stringa);    
    
  }

  free(config_file);

*/ 
  
  mfm_dir->show();         
  
} // class_mfm_dir


/**************************************************************************
* Callbacks
**************************************************************************/

void class_mfm_dir::mfm_dir_collapse_callback() {

  mfm_dir_browser->load_dir(1);
  
  if (mfm_dir_browser->size() == 1)
    
    mfm_dir_browser->load_dir(1);  
    
    mfm_dir_browser->topline(1);      

} 

  
void class_mfm_dir::mfm_dir_copy_callback() {
  
  if (mfm_dir_browser->value() > 0) {

    char *dir_selected = NULL;

    dir_selected = get_path("COPY DIRECTORY TO...", HOMEDIR);
    
    if (dir_selected != NULL) {

      char *command = NULL;

//    asprintf(&command, "mfmexec 'Copying directory...' . 'cp -r '%s' %s 2>&1' &", mfm_dir_browser->get_dir(0), dir_selected);
      asprintf(&command, "mfmexec 'COPYING DIRECTORY...' . 'cp -r -v '%s' %s 2>&1' &", mfm_dir_browser->get_dir(0), dir_selected);

      system(command);

      xfree(&command);          
			
      free(dir_selected);  
      
      start_timeout();
      
    } 

  }   

} 

    
void class_mfm_dir::mfm_dir_move_callback() {

  if (mfm_dir_browser->value() > 0) {

    char *dir_selected = NULL;

    dir_selected = get_path("MOVE DIRECTORY TO...", HOMEDIR);
    
    if (dir_selected != NULL) {

      char *command = NULL;

//    asprintf(&command, "mfmexec 'Moving directory...' . 'mv '%s' %s 2>&1' &", mfm_dir_browser->get_dir(0), dir_selected);
      asprintf(&command, "mfmexec 'MOVING DIRECTORY...' . 'mv -v -n '%s' %s 2>&1' &", mfm_dir_browser->get_dir(0), dir_selected);

      system(command);

      xfree(&command);          
			
      free(dir_selected);  
      
      start_timeout();
      
    } 

  }   

} 

  
void class_mfm_dir::mfm_dir_soft_link_callback() {

  if (mfm_dir_browser->value() > 0) {

    char *dir_selected = NULL;

    dir_selected = get_path("SOFT LINK TO...", HOMEDIR);
    
    if (dir_selected != NULL) {

      char *command = NULL;
						
      asprintf(&command, "mfmexec 'SOFT LINKING...' . 'ln -s -f -v '%s' %s 2>&1' &", mfm_dir_browser->get_dir(0), dir_selected);

      system(command);

      xfree(&command);          
			
      free(dir_selected);  

      start_timeout();
      
    } 

  }   

} 

  
void class_mfm_dir::mfm_dir_hard_link_callback() {

  if (mfm_dir_browser->value() > 0) {

    char *dir_selected = NULL;

    dir_selected = get_path("HARD LINK TO...", HOMEDIR);
    
    if (dir_selected != NULL) {

      char *command = NULL;
						
      asprintf(&command, "mfmexec 'HARD LINKING...' . 'ln -f -v '%s' %s 2>&1' &", mfm_dir_browser->get_dir(0), dir_selected);

      system(command);

      xfree(&command);          
			
      free(dir_selected);  

      start_timeout();
      
    } 

  }   

} 

  
void class_mfm_dir::mfm_dir_browse_callback() {

  if (mfm_dir_browser->value() > 0)
   
    new class_mfm_window(mfm_dir_browser->get_dir(0));

} 

  
void class_mfm_dir::mfm_dir_terminal_callback() {

  if (mfm_dir_browser->value() > 0) {

    char *command = NULL;

	  asprintf(&command, "cd %s; %s &", mfm_dir_browser->get_dir(0), TERMINAL);					

    system(command);

    xfree(&command);          
			
  }   

} 

  
void class_mfm_dir::mfm_dir_trash_callback() {

  if (mfm_dir_browser->value() > 0) {

    char *command = NULL;

	  asprintf(&command, "mv '%s' '%s' &", mfm_dir_browser->get_dir(0), TRASHCANDIR);					

    system(command);

    xfree(&command);  
            
    start_timeout();    
			
  }   

} 

  
void class_mfm_dir::mfm_dir_delete_callback() {

  if (mfm_dir_browser->value() > 0) 
  
    if (get_confirm("DELETING DIRECTORY...", "OK to delete selected item(s) ?")) {  

      char *command = NULL;

	    asprintf(&command, "rm -Rf '%s' &", mfm_dir_browser->get_dir(0));					

      system(command);

      xfree(&command);          

      start_timeout();
      			
    }   

} 
  
  
void class_mfm_dir::mfm_dir_exit_callback() {

  delete this->mfm_dir;
  delete this;

} // mfm_dir_exit_callback


void class_mfm_dir::mfm_dir_help_callback() {

  system("mfmhelp /usr/local/share/doc/mfm.html#menu_dir &");

} // mfm_dir_help_callback
