/*
 * Copyright (c) 2024 Ross Cunniff
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

namespace sys {

// glob() flags
const
    GLOB_ERR = 0x00000001,      // Return upon a read error instead of continuing
    GLOB_MARK = 0x00000002,     // Append a slash to each path which is a dir
    GLOB_NOSORT = 0x00000004,   // Don't sort the returned pathnames
    GLOB_NOCHECK = 0x00000008,  // If no pattern matches, return orig pattern
    GLOB_NOESCAPE = 0x00000010; // Don't allow backslash to be used as an escape
// glob() return values
const
    GLOB_SUCCESS = 0,
    GLOB_NOSPACE = -1,
    GLOB_ABORTED = -2,
    GLOB_NOMATCH = -3;

// Structure for glob()
class GlobClass {
    public var result;          // From GLOB_*, above
    public var paths;           // If result == GLOB_SUCCESS
}

// Modes for chmod and stat
const
    S_IFDIR = 0x4000,
    S_IFLNK = 0xA000, // NOTE: 2 bits are set!
    S_IRUSR = 0x0100,
    S_IWUSR = 0x0080,
    S_IXUSR = 0x0040,
    S_IRGRP = 0x0020,
    S_IWGRP = 0x0010,
    S_IXGRP = 0x0008,
    S_IROTH = 0x0004,
    S_IWOTH = 0x0002,
    S_IXOTH = 0x0001;

// Error codes from errno()
const
    EPERM = 1,          // Operation not permitted
    ENOENT = 2,         // No such file or directory
    ESRCH = 3,          // No such process
    EINTR = 4,          // Interrupted system call
    EIO = 5,            // I/O error
    ENXIO = 6,          // No such device or address
    E2BIG = 7,          // Argument list too long
    ENOEXEC = 8,        // Exec format error
    EBADF = 9,          // Bad file number
    ECHILD = 10,        // No child processes
    EAGAIN = 11,        // Try again
    ENOMEM = 12,        // Out of memory
    EACCES = 13,        // Permission denied
    EFAULT = 14,        // Bad address
    ENOTBLK = 15,       // Block device required
    EBUSY = 16,         // Device or resource busy
    EEXIST = 17,        // File exists
    EXDEV = 18,         // Cross-device link
    ENODEV = 19,        // No such device
    ENOTDIR = 20,       // Not a directory
    EISDIR = 21,        // Is a directory
    EINVAL = 22,        // Invalid argument
    ENFILE = 23,        // File table overflow
    EMFILE = 24,        // Too many open files
    ENOTTY = 25,        // Not a typewriter
    ETXTBSY = 26,       // Text file busy
    EFBIG = 27,         // File too large
    ENOSPC = 28,        // No space left on device
    ESPIPE = 29,        // Illegal seek
    EROFS = 30,         // Read-only file system
    EMLINK = 31,        // Too many links
    EPIPE = 32,         // Broken pipe
    EDOM = 33,          // Math argument out of domain of func
    ERANGE = 34;        // Math result not representable

// Signals for kill() and waitpid()
const
    SIGHUP = 1,
    SIGINT = 2,
    SIGQUIT = 3,
    SIGILL = 4,
    SIGTRAP = 5,
    SIGABRT = 6,
    SIGIOT = 6,
    SIGBUS = 7,
    SIGFPE = 8,
    SIGKILL = 9,
    SIGUSR1 = 10,
    SIGSEGV = 11,
    SIGUSR2 = 12,
    SIGPIPE = 13,
    SIGALRM = 14,
    SIGTERM = 15,
    SIGSTKFLT = 16,
    SIGCHLD = 17,
    SIGCONT = 18,
    SIGSTOP = 19,
    SIGTSTP = 20,
    SIGTTIN = 21,
    SIGTTOU = 22,
    SIGURG = 23,
    SIGXCPU = 24,
    SIGXFSZ = 25,
    SIGVTALRM = 26,
    SIGPROF = 27,
    SIGWINCH = 28,
    SIGIO = 29,
    SIGPWR = 30,
    SIGSYS = 31;

// Structure for stat() - this is an intersection of the Linux, OSX,
// and Windows stat structures
class StatClass {
    public var st_mode;         // From S_*, above
    public var st_uname;        // User *name* (or nil on Windows)
    public var st_gname;        // Group *name* (or nil on Windows)
    public var st_size;         // Long size of the file, in bytes
    public var st_atime;        // Long access time of the file, in [sec,nsec]
    public var st_mtime;        // Long modification time of the file, in [sec,nsec]
    public var st_ctime;        // Long status change time of the file, in [sec,nsec]
}

// Structure returned by waitpid()
class WaitClass {
    public var exited;          // True if child exited normally
    public var status;          // Exit status if exited normally
    public var signaled;        // True if child exited via a signal
    public var termsig;         // Termination signal if signalled
}

// Structure used by localtime, strftime, and strptime
class TimeClass {
    public var tm_sec;    // Seconds (0-60)
    public var tm_min;    // Minutes (0-59)
    public var tm_hour;   // Hours (0-23)
    public var tm_mday;   // Day of the month (1-31)
    public var tm_mon;    // Month (0-11)
    public var tm_year;   // Year - 1900
    public var tm_wday;   // Day of the week (0-6, Sunday = 0)
    public var tm_yday;   // Day in the year (0-365, 1 Jan = 0)
    public var tm_isdst;  // Daylight saving time
}

// System extern procs
extern
    // File system
    chmod,//("filename", mode)
    chown,//("filename", "owner")
    chgrp,//("filename", "grp")
    stat,//("filename")                 // Returns a new StatClass object
    utime,//("filename",[atime,mtime])
    mkdir,//("path")
    rmdir,//("path")
    rename,//("srcname","dstname")
    link,//("srcpath","dstpath")
    unlink,//("path")
    symlink,//("srcpath","dstpath")
    truncate,//("path",length)
    readlink,//("path")
    glob,//("wildcard",[opt-flags])     // Returns a List of strings

    // Process environment
    chdir,//("path")
    getcwd,//()
    getenv,//("name")
    putenv,//("name=val")

    // Process manipulation/status
    getpid,//()
    getppid,//()
    fork,//()
    waitpid,//(pid)                     // Returns a new WaitClass object
    kill,//(pid,sig)
    exec,//("path",{"arg","arg",...}
    system,//("command")

    // Time handling
    time,//()                           // Returns tv_sec
    gettimeofday,//()                   // Returns [tv_sec,tv_usec]
    localtime,//([tv_sec])              // Returns a new TimeClass object
    gmtime,//([tv_sec])                 // Returns a new TimeClass object
    strftime,//(["format"[, timeObj]])  // Returns a string or wide string
    strptime,//("timestamp"[, "format"])// Returns a new TimeClass object
    mktime,//(timeObj[, modif])         // Returns tv_sec - NOTE: Modifies timeObj if modif is true

    strerror,//([errno])                // Returns string of optional errno
    errno;//()

}

using extern "libsys";