//********************************************************************************
//* File       : CsvFile.hpp                                                     *
//* Author     : Mahlon R. Smith                                                 *
//*              Copyright (c) 2024-2026 Mahlon R. Smith, The Software Samurai   *
//*                  GNU GPL copyright notice located below                      *
//* Date       : 05-Apr-2026                                                     *
//* Version    : (see AppVersion string)                                         *
//*                                                                              *
//* Description: General definitions for file access and analysis.               *
//*                                                                              *
//********************************************************************************

//****************
//* Header Files *
//****************
// See CsvView.hpp for duplicates
#include <limits.h>        //* for realpath() and PATH_MAX
#include <dirent.h>        //* Read directory entries
#include <filesystem>      //* std::filesystem (C++17)
#include <dirent.h>        //* Read directory entries
#include <sys/stat.h>      //* Define stat(), lstat(), etc.

//* The following c-type structures defined in the standard header files 
//* need to be C++ data types: stat{} dirent{}, etc.
typedef struct statx FileStats ;
typedef struct dirent64 deStats ;
typedef struct tm Tm ;

//*****************
//* Constant Data *
//*****************
const short MAX_PATH  = PATH_MAX ;     //* Size of buffer to hold a Posix-compliant path/filename
const short MAX_FNAME = 256 ;          //* Size of buffer to hold a Posix-compliant filename

//* Local definitions for file type encoded in the *
//* "st_mode" element of the stat{} structure.     *
enum fmFType : short { fmDIR_TYPE,   fmREG_TYPE,  fmLINK_TYPE, fmCHDEV_TYPE, 
                       fmBKDEV_TYPE, fmFIFO_TYPE, fmSOCK_TYPE, fmUNKNOWN_TYPE, fmTYPES } ;

#if STAT_X != 0
#else    // FUNCTIONAL
#endif   // FUNCTIONAL
#if STAT_X != 0
#else    // FUNCTIONAL
#endif   // FUNCTIONAL
//* Class for reporting the system local date/time.                            *
//* ---------------------------------------------------------------------------*
#define DECODE_TZ (1)   // if non-zero, decode time-zone fields of localTime
const int64_t maxETIME32 = 0x07FFFFFFF,      // largest 32-bit time_t
              minETIME32 = -maxETIME32 - 1 ; // smallest 32-bit time_t
const short ltFMT_LEN = 16 ;                 // length of time string buffers
//* Important note about the year 2038 bug:                                    *
//* Because 'time_t' is defined as a signed, 32-bit value on 32-bit systems,   *
//* time reporting will break down for date/time values                        *
//*                     >= 19 Jan 2038 at 11:14:08                             *
//* For this reason and for others, we have defined our own local-time class.  *
//* This class uses a signed, 64-bit value for storing the epoch time.         *
//* It is hoped that all Linux systems will have been updated long before this *
//* becomes an issue; however, even now (2013), some applications are using    *
//* date/time manipulations that exceed the 32-bit limit. BEWARE!!             *
//* NOTE: time arithmetic should always be performed on signed 64-bit values.  *
//*                                                                            *
class localTime
{
   public:
   localTime ( void ) { this->reset() ; }
   void reset ( void )
   {  //* Set to epoch date: Thursday, 01 Jan. 1970 @ 08:00:00
      this->sysepoch = ZERO ;
      this->epoch = ZERO ;
      this->day = 4 ;
      this->year = 1970 ;
      this->month = this->date = 1 ;
      this->hours = 8 ;
      this->minutes = this->seconds = ZERO ;
      this->julian = ZERO ;
      #if DECODE_TZ != 0   // time-zone data
      *this->timezone = NULLCHAR ;
      *this->utc_zone  = NULLCHAR ;
      this->gmtoffset = ZERO ;
      this->dst       = false ;
      #endif   // DECODE_TZ
   }
   int64_t  epoch ;        //* Seconds since the epoch (01-Jan-1970)
   time_t   sysepoch ;     //* system epoch time (see note)
   uint16_t day ;          //* Day of the week (0 == Sun, ..., 6 == Sat)
   uint16_t date ;         //* Day of the month (1-[28|29|30|31])
   uint16_t month ;        //* Month of the year (1 == Jan, ... 12 == Dec)
   uint16_t year ;         //* Year (four digit year)
   uint16_t hours ;        //* Time of day, hour (0-23)
   uint16_t minutes ;      //* Time of day, minutes (0-59)
   uint16_t seconds ;      //* Time of day, seconds (0-59)
   uint16_t julian ;       //* Completed days since beginning of year

   #if DECODE_TZ != 0   // time-zone data
   // See DecodeEpochTime method for more information.
   char     timezone[ltFMT_LEN] ; //* string representing the local time zone (useless)
   char     utc_zone[ltFMT_LEN] ; //* string representing the UTC offset for local time zone
   short    gmtoffset ;    //* Expressed as (signed) number of seconds offset from UTC+0:00
   bool     dst ;          //* 'true' if daylight savings time in effect,
                           //* 'false if not DST or info not available
   #endif   // DECODE_TZ
} ;

//* Class definition for target file stats.                      *
//* (adapted from TreeNode structure in FileMangler application) *
class tnFName
{
   public:
   ~tnFName ( void )          //* Destructor
   { /* nothing to do */ }
   tnFName ( void )           //* Constructor
   { this->ReInit () ; }

   void ReInit(void)          //* Set all members to default values
   {
      this->fSpec[0] = NULLCHAR ;
      this->fName[0] = NULLCHAR ;
      this->fType    = fmTYPES ;
      this->fBytes   = ZERO ;
      this->modTime.day  = this->modTime.date  = this->modTime.month = 
      this->modTime.year = this->modTime.hours = this->modTime.minutes = 
      this->modTime.seconds = ZERO ;
      this->readAcc  = false ;
      this->writeAcc = false ;
      // NOTE: data member, rawStats is left unitialized
   }

   //* Data Members *
   char        fSpec[MAX_PATH] ;  //* Filespec (path) string
   char        fName[MAX_FNAME] ; //* Filename string
   fmFType     fType ;     //* File type (enum fmFType)
   uint64_t    fBytes ;    //* File size (in bytes)
   localTime   modTime ;   //* Date/Time file last modified (human readable)
   FileStats   rawStats ;  //* Copy of system's "stat" structure (all file info)
   bool        readAcc ;   //* 'true' if user has read access to file
   bool        writeAcc ;  //* 'true' if user has write access to file
} ;
