/*
 * ==================================================================================
 * File I/O Header - File Management and Transfer Operations
 *
 * ISA Project
 * Author: Roman Necas (xnecasr00)
 * Date: 13. October 2025
 *
 * PURPOSE:
 * This header defines the file management layer for the ICMP covert channel
 * file transfer application. It provides abstractions for chunk-based file
 * reading/writing, path validation, and transfer statistics tracking.
 *
 * RESPONSIBILITIES:
 * - File opening and validation (read/write modes)
 * - Chunk-based file I/O for network transmission
 * - Fragment tracking for multi-packet transfers
 * - Path normalization and security validation
 * - File metadata preservation (permissions, timestamps)
 * - Transfer statistics and progress tracking
 *
 * SECURITY FEATURES:
 * - Path traversal prevention (../.. attacks)
 * - Permission validation before file access
 * - Atomic file operations (temp file + rename)
 * - Secure file deletion with overwrite
 * - Basename extraction to prevent path disclosure
 *
 * CHUNK-BASED I/O:
 * Files are read and written in chunks to match network payload size
 * (MAX_PAYLOAD_SIZE = 1400 bytes). This allows efficient streaming of
 * large files without loading entire file into memory.
 *
 * FRAGMENTATION SUPPORT:
 * Large files are automatically divided into fragments, each containing
 * one chunk of data. The file_manager_t structure tracks fragment numbers
 * for proper reassembly on the receiving end.
 * ==================================================================================
 */

#ifndef FILE_IO_H
#define FILE_IO_H

#include "common.h"

/*
 * ==================================================================================
 * FILE MANAGER STRUCTURE
 * ==================================================================================
 */

/*
 * file_manager_t - File I/O state management
 *
 * This structure encapsulates all state required for chunk-based file operations.
 * It supports both reading (client mode - sending file) and writing (server mode -
 * receiving file) with automatic fragment tracking.
 *
 * LIFECYCLE:
 * 1. Allocated by caller (typically on stack or in session structure)
 * 2. Initialized by file_manager_open_read() or file_manager_open_write()
 * 3. Used for file_manager_read_chunk() or file_manager_write_chunk() calls
 * 4. Cleaned up by file_manager_cleanup() (closes file, frees memory)
 *
 * USAGE PATTERNS:
 *
 * Client mode (reading file to send):
 *   file_manager_t fm;
 *   file_manager_open_read(&fm, "/path/to/file.txt");
 *   while (!file_manager_is_complete(&fm)) {
 *       uint8_t chunk[MAX_PAYLOAD_SIZE];
 *       size_t bytes_read;
 *       file_manager_read_chunk(&fm, chunk, MAX_PAYLOAD_SIZE, &bytes_read);
 *       send_data_packet(chunk, bytes_read);
 *   }
 *   file_manager_cleanup(&fm);
 *
 * Server mode (writing received file):
 *   file_manager_t fm;
 *   file_manager_open_write(&fm, "received_file.txt");
 *   file_manager_set_file_size(&fm, expected_size);  // From metadata
 *   for each received chunk:
 *       file_manager_write_chunk(&fm, chunk_data, chunk_size);
 *   file_manager_cleanup(&fm);
 *
 * THREAD SAFETY:
 * This structure is NOT thread-safe. Each file transfer should have its own
 * file_manager_t instance.
 *
 * MEMORY MANAGEMENT:
 * The filename field is dynamically allocated by file_manager_open_*() and
 * freed by file_manager_cleanup(). Always call cleanup to prevent leaks.
 */
typedef struct {
    /*
     * file_handle - Standard C FILE pointer for I/O operations
     *
     * This is the underlying file stream used for all read/write operations.
     * Opened by fopen() in file_manager_open_read() or file_manager_open_write().
     *
     * Modes:
     * - Read mode: fopen(filename, "rb") - binary read
     * - Write mode: fopen(filename, "wb") - binary write (overwrites existing)
     *
     * Values:
     * - Non-NULL: Valid open file
     * - NULL: No file open or error occurred
     *
     * Closed by file_manager_cleanup() using SAFE_CLOSE macro (fclose).
     */
    FILE *file_handle;

    /*
     * filename - Full path to the file
     *
     * Dynamically allocated string containing the complete path to the file
     * being read or written. This is used for error messages and logging.
     *
     * Allocation:
     * - Allocated by strdup() in file_manager_open_read() or file_manager_open_write()
     * - Freed by file_manager_cleanup() using SAFE_FREE macro
     *
     * Content:
     * - Client mode: Path specified by user (can include directories)
     * - Server mode: Basename only (extracted from metadata, no path components)
     *
     * Security note:
     * Server mode ALWAYS strips directory components to prevent path traversal
     * attacks (e.g., "../../../etc/passwd" becomes "passwd").
     */
    char *filename;

    /*
     * file_size - Total size of the file in bytes
     *
     * Client mode: Determined by stat() or fseek(SEEK_END) during file_manager_open_read()
     * Server mode: Set by file_manager_set_file_size() from START packet metadata
     *
     * Used to:
     * - Calculate total_fragments (file_size / chunk_size + 1)
     * - Verify transfer completion (bytes_processed == file_size)
     * - Display progress percentage
     * - Pre-allocate space on server (optional)
     *
     * Range: 0 to UINT64_MAX (theoretical max ~16 exabytes)
     * Practical limit: Limited by filesystem and available disk space
     */
    uint64_t file_size;

    /*
     * bytes_processed - Number of bytes read or written so far
     *
     * Incremented by file_manager_read_chunk() or file_manager_write_chunk()
     * after each successful operation.
     *
     * Used to:
     * - Track transfer progress: (bytes_processed / file_size) * 100
     * - Detect completion: (bytes_processed >= file_size)
     * - Calculate current file position for seeking
     * - Verify expected vs actual bytes received (server mode)
     *
     * Invariant: bytes_processed <= file_size (violation indicates corruption)
     */
    uint64_t bytes_processed;

    /*
     * total_fragments - Total number of fragments for transfer
     *
     * Calculated during file_manager_open_read() as:
     *   total_fragments = (file_size + chunk_size - 1) / chunk_size
     *
     * This is the ceiling division, ensuring all bytes are covered.
     *
     * Examples (chunk_size = 1400):
     * - 500 byte file: 1 fragment
     * - 1400 byte file: 1 fragment
     * - 1401 byte file: 2 fragments
     * - 1 MB file: 750 fragments
     *
     * Used to:
     * - Populate fragment_total field in IFTP header
     * - Display progress: "Fragment 500/750"
     * - Server validation: Verify received fragment numbers are valid
     */
    uint32_t total_fragments;

    /*
     * current_fragment - Current fragment being processed (0-based)
     *
     * Client mode: Incremented after each file_manager_read_chunk() call
     * Server mode: Set based on fragment_current field in received DATA packet
     *
     * Range: 0 to (total_fragments - 1)
     *
     * Used to:
     * - Populate fragment_current field in IFTP header
     * - Track read position in file
     * - Detect duplicate or out-of-order fragments (server mode)
     *
     * Invariant: current_fragment < total_fragments (unless complete)
     */
    uint32_t current_fragment;

    /*
     * read_mode - File operation mode flag
     *
     * Values:
     * - 1: Read mode (client sending file)
     * - 0: Write mode (server receiving file)
     *
     * Determines:
     * - Which operations are valid (read vs write)
     * - How file_size is determined (stat vs metadata)
     * - Whether fragments are generated (read) or validated (write)
     * - Error message context
     *
     * Set by file_manager_open_read() or file_manager_open_write().
     */
    int read_mode;

    /*
     * file_permissions - File permissions for preservation
     *
     * POSIX file mode bits (mode_t from sys/stat.h):
     * - Owner: read (0400), write (0200), execute (0100)
     * - Group: read (0040), write (0020), execute (0010)
     * - Other: read (0004), write (0002), execute (0001)
     * - Special: setuid (04000), setgid (02000), sticky (01000)
     *
     * Client mode:
     * - Read from source file using stat() in file_manager_open_read()
     * - Transmitted in START packet metadata (future enhancement)
     *
     * Server mode:
     * - Received from START packet metadata (future enhancement)
     * - Applied to written file using chmod() in file_manager_cleanup()
     *
     * Default: 0644 (rw-r--r--) if not specified
     *
     * Security note: Permissions are sanitized to prevent setuid/setgid
     * on received files.
     */
    mode_t file_permissions;

    /*
     * last_modified - Last modification time (Unix timestamp)
     *
     * Seconds since Unix epoch (1970-01-01 00:00:00 UTC).
     *
     * Client mode: Read from source file using stat()
     * Server mode: Can be set on received file using utime() (future enhancement)
     *
     * Used to preserve file metadata across transfer.
     */
    time_t last_modified;
} file_manager_t;

/*
 * ==================================================================================
 * FILE TRANSFER STATISTICS STRUCTURE
 * ==================================================================================
 */

/*
 * file_transfer_stats_t - File transfer performance metrics
 *
 * This structure tracks timing and throughput statistics for a file transfer
 * session. It complements network_stats_t which tracks packet-level metrics.
 *
 * LIFECYCLE:
 * 1. Initialized by file_transfer_stats_init() (zeros fields, sets start_time)
 * 2. Updated by file_transfer_stats_update() after each chunk transfer
 * 3. Finalized by file_transfer_stats_finalize() (sets end_time, calculates rate)
 * 4. Displayed by file_transfer_stats_print()
 *
 * USAGE:
 *   file_transfer_stats_t stats;
 *   file_transfer_stats_init(&stats);
 *   stats.total_bytes = file_size;
 *   // ... transfer chunks ...
 *   file_transfer_stats_update(&stats, chunk_size);
 *   file_transfer_stats_finalize(&stats);
 *   file_transfer_stats_print(&stats);
 */
typedef struct {
    /*
     * total_bytes - Total bytes to transfer
     *
     * Set from file_manager_t.file_size at start of transfer.
     * Used to calculate progress percentage.
     */
    uint64_t total_bytes;

    /*
     * bytes_transferred - Bytes successfully transferred
     *
     * Incremented by file_transfer_stats_update() after each chunk.
     * Should equal total_bytes when transfer completes.
     */
    uint64_t bytes_transferred;

    /*
     * fragments_sent - Number of fragments sent (client mode)
     *
     * Incremented after each DATA packet transmission.
     * Used to track progress: "Sent fragment 500/750"
     */
    uint32_t fragments_sent;

    /*
     * fragments_received - Number of fragments received (server mode)
     *
     * Incremented after each DATA packet reception and write.
     * May be less than expected if transfer is interrupted.
     */
    uint32_t fragments_received;

    /*
     * start_time - Transfer start timestamp (Unix time)
     *
     * Set by file_transfer_stats_init() using time(NULL).
     * Used to calculate total transfer duration.
     */
    time_t start_time;

    /*
     * end_time - Transfer end timestamp (Unix time)
     *
     * Set by file_transfer_stats_finalize() using time(NULL).
     * Used to calculate total transfer duration.
     */
    time_t end_time;

    /*
     * transfer_rate - Transfer rate in bytes per second
     *
     * Calculated by file_transfer_stats_finalize() as:
     *   transfer_rate = bytes_transferred / (end_time - start_time)
     *
     * Useful for performance analysis and comparison.
     * Typical values: 10 KB/s to 10 MB/s depending on network conditions.
     */
    double transfer_rate;
} file_transfer_stats_t;

/*
 * ==================================================================================
 * CORE FILE MANAGER FUNCTIONS
 * ==================================================================================
 */

/*
 * file_manager_open_read - Open file for reading in client mode
 *
 * Opens the specified file for binary reading and initializes the file_manager_t
 * structure. This function:
 * 1. Validates file exists and is readable
 * 2. Opens file with fopen(filename, "rb")
 * 3. Determines file size using fseek(SEEK_END) + ftell()
 * 4. Reads file permissions and modification time using stat()
 * 5. Calculates total_fragments based on file_size and chunk_size
 * 6. Initializes tracking fields (bytes_processed=0, current_fragment=0)
 *
 * VALIDATION:
 * - File must exist (checked with access(F_OK))
 * - File must be readable (checked with access(R_OK))
 * - File must be a regular file (not directory, device, symlink)
 * - File size must be > 0 (empty files rejected)
 *
 * ERROR HANDLING:
 * - Returns -1 if file doesn't exist, is not readable, or is empty
 * - Returns -1 if fopen() fails (permissions, too many open files, etc.)
 * - Sets error context with detailed message
 *
 * @param fm: File manager structure to initialize (output parameter)
 * @param filename: Path to file to read (can be relative or absolute)
 *
 * @return:
 *    0: Success - file opened and ready for reading
 *   -1: Failure - error details in error context
 *
 * EXAMPLE:
 *   file_manager_t fm;
 *   if (file_manager_open_read(&fm, "/path/to/file.txt") < 0) {
 *       error_print_last();
 *       return -1;
 *   }
 *   printf("File size: %lu bytes, %u fragments\n", fm.file_size, fm.total_fragments);
 */
int file_manager_open_read(file_manager_t *fm, const char *filename);

/*
 * file_manager_open_write - Open file for writing in server mode
 *
 * Opens the specified file for binary writing and initializes the file_manager_t
 * structure. This function:
 * 1. Extracts basename from filename (security: prevent path traversal)
 * 2. Validates output path is safe (no ../.. components)
 * 3. Opens file with fopen(basename, "wb") in current directory
 * 4. Initializes write mode tracking fields
 *
 * SECURITY FEATURES:
 * - ALWAYS strips directory components from filename
 *   * "../../../etc/passwd" → "passwd"
 *   * "/tmp/evil" → "evil"
 *   * "subdir/file.txt" → "file.txt"
 * - Validates filename doesn't contain path traversal sequences
 * - Creates file in current working directory only
 * - Uses safe permissions (0644) for new files
 *
 * OVERWRITE BEHAVIOR:
 * - Existing files are OVERWRITTEN without warning
 * - Consider using file_exists() check before calling if needed
 *
 * FILE SIZE:
 * - file_size is initially 0 - must be set by file_manager_set_file_size()
 *   after receiving START packet metadata
 *
 * @param fm: File manager structure to initialize (output parameter)
 * @param filename: Basename of file to write (path components stripped)
 *
 * @return:
 *    0: Success - file opened and ready for writing
 *   -1: Failure - error details in error context
 *
 * EXAMPLE (Server):
 *   file_manager_t fm;
 *   // metadata->filename might be "../../../evil"
 *   if (file_manager_open_write(&fm, metadata->filename) < 0) {
 *       error_print_last();
 *       return -1;
 *   }
 *   // File is safely created as "./evil" in current directory
 *   file_manager_set_file_size(&fm, metadata->file_size);
 */
int file_manager_open_write(file_manager_t *fm, const char *filename);

/*
 * file_manager_read_chunk - Read next chunk of data from file
 *
 * Reads up to chunk_size bytes from the current file position and advances
 * the internal state (bytes_processed, current_fragment).
 *
 * BEHAVIOR:
 * - Reads from current file position (maintained by FILE* stream)
 * - Returns actual bytes read (may be less than chunk_size at end of file)
 * - Increments bytes_processed by bytes read
 * - Increments current_fragment after each read
 * - Safe to call repeatedly until file_manager_is_complete() returns true
 *
 * END OF FILE:
 * - Last chunk may be smaller than chunk_size (e.g., 500 bytes instead of 1400)
 * - bytes_read parameter contains actual bytes read (0 indicates EOF)
 * - Caller should check bytes_read to determine chunk size
 *
 * ERROR HANDLING:
 * - Returns -1 if read_mode is not set (file opened for write)
 * - Returns -1 if fread() fails (disk error, file removed, etc.)
 * - Returns -1 if file_handle is NULL (file not open)
 *
 * @param fm: Initialized file manager (must be in read mode)
 * @param buffer: Buffer to receive chunk data (min MAX_PAYLOAD_SIZE bytes)
 * @param chunk_size: Maximum bytes to read (typically MAX_PAYLOAD_SIZE = 1400)
 * @param bytes_read: Output parameter for actual bytes read
 *
 * @return:
 *    0: Success - chunk read successfully
 *   -1: Failure - error details in error context
 *
 * EXAMPLE:
 *   uint8_t chunk[MAX_PAYLOAD_SIZE];
 *   size_t bytes_read;
 *   while (file_manager_read_chunk(&fm, chunk, MAX_PAYLOAD_SIZE, &bytes_read) == 0) {
 *       if (bytes_read == 0) break;  // EOF
 *       send_data_packet(chunk, bytes_read);
 *   }
 */
int file_manager_read_chunk(file_manager_t *fm, void *buffer, size_t chunk_size, size_t *bytes_read);

/*
 * file_manager_write_chunk - Write chunk of data to file
 *
 * Writes bytes_to_write bytes from buffer to the current file position and
 * advances the internal state (bytes_processed, current_fragment).
 *
 * BEHAVIOR:
 * - Writes to current file position (maintained by FILE* stream)
 * - Writes exactly bytes_to_write bytes (partial writes considered errors)
 * - Increments bytes_processed by bytes written
 * - Can be called in any order (out-of-order chunks handled if seeking enabled)
 *
 * FILE SIZE VALIDATION:
 * - Checks that bytes_processed + bytes_to_write <= file_size (if file_size set)
 * - Prevents writing more data than expected from metadata
 * - Returns error if write would exceed expected file size
 *
 * ERROR HANDLING:
 * - Returns -1 if read_mode is set (file opened for read)
 * - Returns -1 if fwrite() fails (disk full, permissions, etc.)
 * - Returns -1 if file_handle is NULL (file not open)
 * - Returns -1 if write would exceed expected file_size
 *
 * @param fm: Initialized file manager (must be in write mode)
 * @param buffer: Chunk data to write
 * @param bytes_to_write: Number of bytes to write
 *
 * @return:
 *    0: Success - chunk written successfully
 *   -1: Failure - error details in error context
 *
 * EXAMPLE:
 *   // After receiving DATA packet with chunk
 *   if (file_manager_write_chunk(&fm, chunk_data, chunk_size) < 0) {
 *       error_print_last();
 *       send_nack_packet(ERR_FILE_ERROR);
 *       return -1;
 *   }
 */
int file_manager_write_chunk(file_manager_t *fm, const void *buffer, size_t bytes_to_write);

/*
 * file_manager_seek_to_position - Seek to specific byte offset in file
 *
 * Moves the file position to the specified byte offset using fseek().
 * Used for random-access writes when packets arrive out of order.
 *
 * USAGE:
 * Server mode can use this to handle out-of-order fragment reception:
 *   fragment_offset = fragment_number * chunk_size;
 *   file_manager_seek_to_position(&fm, fragment_offset);
 *   file_manager_write_chunk(&fm, chunk_data, chunk_size);
 *
 * LIMITATIONS:
 * - position must be <= file_size
 * - Seeking beyond EOF is prevented
 *
 * @param fm: Initialized file manager
 * @param position: Byte offset from start of file (0-based)
 *
 * @return:
 *    0: Success
 *   -1: Failure - invalid position or fseek() error
 */
int file_manager_seek_to_position(file_manager_t *fm, uint64_t position);

/*
 * file_manager_get_fragment_info - Get current and total fragment numbers
 *
 * Returns fragment tracking information for display or packet header population.
 *
 * @param fm: File manager instance
 * @param current: Output parameter for current_fragment (can be NULL)
 * @param total: Output parameter for total_fragments (can be NULL)
 *
 * @return:
 *    0: Success
 *   -1: Failure - fm is NULL
 */
int file_manager_get_fragment_info(const file_manager_t *fm, uint32_t *current, uint32_t *total);

/*
 * file_manager_get_file_size - Get total file size
 *
 * @param fm: File manager instance
 * @return: File size in bytes, or 0 if fm is NULL
 */
uint64_t file_manager_get_file_size(const file_manager_t *fm);

/*
 * file_manager_get_bytes_processed - Get bytes processed so far
 *
 * @param fm: File manager instance
 * @return: Bytes read or written, or 0 if fm is NULL
 */
uint64_t file_manager_get_bytes_processed(const file_manager_t *fm);

/*
 * file_manager_get_filename - Get filename
 *
 * @param fm: File manager instance
 * @return: Pointer to filename string, or NULL if fm is NULL
 */
const char *file_manager_get_filename(const file_manager_t *fm);

/*
 * file_manager_is_complete - Check if transfer is complete
 *
 * Returns true (1) if bytes_processed >= file_size, false (0) otherwise.
 *
 * @param fm: File manager instance
 * @return: 1 if complete, 0 if not complete or fm is NULL
 */
int file_manager_is_complete(const file_manager_t *fm);

/*
 * file_manager_set_file_size - Set expected file size (server mode)
 *
 * Called after receiving START packet metadata to set the expected file size.
 * Also calculates total_fragments based on file_size.
 *
 * @param fm: File manager instance (must be in write mode)
 * @param file_size: Expected file size from metadata
 */
void file_manager_set_file_size(file_manager_t *fm, uint64_t file_size);

/*
 * file_manager_get_basename - Extract basename from path
 *
 * Extracts the filename component from a path, removing directory components.
 * Used to sanitize filenames received from network.
 *
 * Examples:
 * - "/path/to/file.txt" → "file.txt"
 * - "../../../etc/passwd" → "passwd"
 * - "file.txt" → "file.txt"
 *
 * @param path: Input path (can contain directory components)
 * @param basename: Output buffer for basename
 * @param basename_len: Size of output buffer
 *
 * @return:
 *    0: Success
 *   -1: Failure - path is NULL, empty, or basename_len too small
 */
int file_manager_get_basename(const char *path, char *basename, size_t basename_len);

/*
 * file_manager_cleanup - Close file and free resources
 *
 * Releases all resources associated with the file manager:
 * 1. Closes file using fclose() (SAFE_CLOSE macro)
 * 2. Frees filename string (SAFE_FREE macro)
 * 3. Zeros structure fields
 *
 * SAFE TO CALL MULTIPLE TIMES:
 * Uses SAFE_FREE/SAFE_CLOSE which set pointers to NULL after cleanup.
 *
 * MUST BE CALLED:
 * Failure to call this function leaks a FILE* and memory for filename.
 *
 * @param fm: File manager to clean up
 */
void file_manager_cleanup(file_manager_t *fm);

/*
 * ==================================================================================
 * FILE UTILITY FUNCTIONS
 * ==================================================================================
 */

/*
 * file_exists - Check if file exists
 * @return: 1 if exists, 0 if not exists or error
 */
int file_exists(const char *filename);

/*
 * file_is_readable - Check if file is readable
 * @return: 1 if readable, 0 if not readable or error
 */
int file_is_readable(const char *filename);

/*
 * file_is_writable - Check if file is writable
 * @return: 1 if writable, 0 if not writable or error
 */
int file_is_writable(const char *filename);

/*
 * file_get_size - Get file size using stat()
 * @return: File size in bytes, or 0 on error
 */
uint64_t file_get_size(const char *filename);

/*
 * file_get_permissions - Get file permissions
 * @return: 0 on success, -1 on error
 */
int file_get_permissions(const char *filename, mode_t *permissions);

/*
 * file_set_permissions - Set file permissions
 * @return: 0 on success, -1 on error
 */
int file_set_permissions(const char *filename, mode_t permissions);

/*
 * file_get_modification_time - Get last modification time
 * @return: Unix timestamp, or 0 on error
 */
time_t file_get_modification_time(const char *filename);

/*
 * ==================================================================================
 * SAFE FILE OPERATIONS
 * ==================================================================================
 */

/*
 * file_create_temp - Create temporary file with unique name
 *
 * Creates a temporary file using mkstemp() with the provided template.
 * Template must end with "XXXXXX" which will be replaced with unique suffix.
 *
 * @param template_path: Template path (e.g., "file_XXXXXX"), modified in place
 * @param template_size: Size of template_path buffer
 * @return: File descriptor of created temp file, or -1 on error
 */
int file_create_temp(char *template_path, size_t template_size);

/*
 * file_atomic_rename - Atomically rename temporary file to final name
 *
 * Uses rename() which is atomic on POSIX systems. If final file exists,
 * it is atomically replaced.
 *
 * @param temp_filename: Temporary file path
 * @param final_filename: Final file path
 * @return: 0 on success, -1 on error
 */
int file_atomic_rename(const char *temp_filename, const char *final_filename);

/*
 * file_secure_delete - Securely delete file with overwrite
 *
 * Overwrites file contents with zeros before unlinking to prevent recovery.
 * Note: May not be effective on SSD/flash storage due to wear leveling.
 *
 * @param filename: File to securely delete
 * @return: 0 on success, -1 on error
 */
int file_secure_delete(const char *filename);

/*
 * file_create_backup - Create backup copy of file
 *
 * Copies filename to filename.bak or filename.bak.N if backup exists.
 *
 * @param filename: File to backup
 * @param backup_filename: Output buffer for backup filename
 * @param backup_size: Size of backup_filename buffer
 * @return: 0 on success, -1 on error
 */
int file_create_backup(const char *filename, char *backup_filename, size_t backup_size);

/*
 * ==================================================================================
 * PATH MANIPULATION FUNCTIONS
 * ==================================================================================
 */

/*
 * path_normalize - Normalize path by resolving . and .. components
 * @return: 0 on success, -1 on error
 */
int path_normalize(const char *input_path, char *output_path, size_t output_size);

/*
 * path_join - Join directory and filename components
 * @return: 0 on success, -1 on error
 */
int path_join(const char *dir, const char *filename, char *output_path, size_t output_size);

/*
 * path_get_directory - Extract directory component from filepath
 * @return: 0 on success, -1 on error
 */
int path_get_directory(const char *filepath, char *directory, size_t directory_size);

/*
 * path_is_absolute - Check if path is absolute (starts with /)
 * @return: 1 if absolute, 0 if relative
 */
int path_is_absolute(const char *path);

/*
 * path_is_safe - Check if path is safe (no .. traversal)
 *
 * Validates path doesn't contain:
 * - ".." components (parent directory traversal)
 * - Null bytes
 * - Excessively long components
 *
 * @return: 1 if safe, 0 if unsafe
 */
int path_is_safe(const char *path);

/*
 * ==================================================================================
 * TRANSFER STATISTICS FUNCTIONS
 * ==================================================================================
 */

/*
 * file_transfer_stats_init - Initialize transfer statistics
 * Sets start_time to current time, zeros other fields.
 */
void file_transfer_stats_init(file_transfer_stats_t *stats);

/*
 * file_transfer_stats_update - Update bytes transferred
 * Increments bytes_transferred and appropriate fragment counter.
 */
void file_transfer_stats_update(file_transfer_stats_t *stats, uint64_t bytes_transferred);

/*
 * file_transfer_stats_finalize - Finalize statistics
 * Sets end_time and calculates transfer_rate.
 */
void file_transfer_stats_finalize(file_transfer_stats_t *stats);

/*
 * file_transfer_stats_print - Print statistics summary
 * Displays total bytes, duration, transfer rate, etc.
 */
void file_transfer_stats_print(const file_transfer_stats_t *stats);

/*
 * file_transfer_stats_get_rate - Get transfer rate
 * @return: Transfer rate in bytes/second
 */
double file_transfer_stats_get_rate(const file_transfer_stats_t *stats);

/*
 * file_transfer_stats_get_progress - Get progress percentage
 * @return: Progress as percentage (0.0 to 100.0)
 */
double file_transfer_stats_get_progress(const file_transfer_stats_t *stats);

#endif /* FILE_IO_H */
