/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CFtpDS.h - description
                             -------------------
    begin                : Mar 19 2003
    copyright            : (C) 2003-2006 by Alexey Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

/***************************************************************************
   This library is free software; you can redistribute it and/or modify it 
   under the terms of the GNU Library General Public License as published by
   the Free Software Foundation; either version 2 of the License, or (at 
   your option) any later version.

   This library 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 Library
   General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/

#include <FL/Fl_Image.h>
#include <FL/Fl_Pixmap.h>

#include <sptk3/CFtpDS.h>
#include <sptk3/CException.h>
#include <sptk3/CSmallPixmaps.h>

#include <ctype.h>
#include <string.h>
#include <stdlib.h>

using namespace std;
using namespace sptk;

static char *next_dir_item(char *p,char **result) {
   char *start = p;
   for (; *start == ' '; start++);
   *result = start;
   start = (char *) strchr(start,' ');
   *start = 0;
   return start + 1;
}

static const CStrings
   month_names("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Nov|Dec","|");

CFieldList *parse_file_info_string(string& file_info) {
   char *ptr = (char *) file_info.c_str();

   char *permissions = 0L;
   char *refcount = 0L;
   char *user_name = 0L;
   char *group_name = 0L;
   char *size = 0L;
   char *month = 0L, *day = 0L, *year = 0L, *time = 0L;
   char *file_name = 0L;
   bool  is_directory = false;
   bool  is_executable = false;

   CDateTime dt;
   const Fl_Image *pixmapPtr = CSmallPixmaps::pixmaps[SXPM_DOCUMENT];    

   if (isdigit(*ptr)) {
      // MS Dos style
      char *dtime = 0L;

      ptr = next_dir_item(ptr,&time);     
      ptr = next_dir_item(ptr, &dtime);

      ptr = next_dir_item(ptr,&size);

      if (strstr(size,"DIR"))
         is_directory = true;
      time[2] = 0;
      time[5] = 0;

      int month   = strtol(time, NULL, 10);
      int day     = strtol(time+3, NULL, 10);
      int year = strtol(time+6, NULL, 10);

      bool pm = false;
      if(strstr(dtime, "PM")) pm = true;
      dtime[2] = 0;
      dtime[5] = 0;
      int hour = strtol(dtime, NULL, 10);
      int min     = strtol(dtime+3, NULL, 10);     
      if(pm) hour+=12;

      if(year<50) year+=2000;
      else year+=1900;

      CDateTime dosDate(year, month, day, hour, min);
      dt = dosDate;
   } else {
      ptr = next_dir_item(ptr,&permissions); 
        // Unix style
      if (permissions[0] == 'd')
         is_directory = true;
      else if (strchr(permissions,'x'))
         is_executable = true;
      ptr = next_dir_item(ptr,&refcount);
      ptr = next_dir_item(ptr,&user_name);
      ptr = next_dir_item(ptr,&group_name);
      ptr = next_dir_item(ptr,&size);
      ptr = next_dir_item(ptr,&month);
      ptr = next_dir_item(ptr,&day);
      ptr = next_dir_item(ptr,&year);
      int m = month_names.indexOf(month) + 1;
      if (m >= 0) {
         int d = atoi(day);
         int y = atoi(year);
         CDateTime unixDate(y,m,d);
         dt = unixDate;
      }
   }

   if (is_directory)
      pixmapPtr = CSmallPixmaps::pixmaps[SXPM_FOLDER];
   else if (is_executable)
      pixmapPtr = CSmallPixmaps::pixmaps[SXPM_EXECUTABLE];

    // skip to the file name
   for (; *ptr == ' '; ptr++);
   file_name = ptr;

   CFieldList *df = new CFieldList(false);

   df->push_back("",false)         = pixmapPtr;
   df->push_back("Name",false)     = file_name;
   df->push_back("Size",false)     = atoi(size);
   df->push_back("Modified",false) = dt;

   (*df)[0].width = 3;
   (*df)[1].width = 30;
   (*df)[2].width = 10;
   (*df)[2].flags = FL_ALIGN_RIGHT;
   (*df)[3].width = 16;

   return df;
}

// read the folder() and move item into the first entry
bool sptk::CFtpDS::open() {
   clear();

   // Connect to the server
   m_ftp.host(m_host,m_port);
   m_ftp.user(m_user);
   m_ftp.password(m_password);
   m_ftp.open();

   // Select the folder
   if (m_folder.length())
      m_ftp.cmd_cd(m_folder);

   CStrings dirlist;
   m_ftp.cmd_list(dirlist);
    //dirlist.print();

   if (dirlist.size()) {
      unsigned cnt = dirlist.size();
      if (m_callback)
         m_callback(cnt,0);
      for (unsigned i = 0; i < cnt; i++) {
         CFieldList *df = parse_file_info_string(dirlist[i]);
         if (df)
            m_list.push_back(df);

         if (m_callback)
            m_callback(cnt,i);
      }
   }

   if (m_callback)
      m_callback(100,100);

   first();

   m_ftp.cmd_quit();
   m_ftp.close();

   m_eof = m_list.size() == 0;

   return !m_eof;
}
