/* Copyright (c) 2020-2021 The Creators of Simphone

   See the file COPYING.LESSER.txt for copying permission.
*/

#ifndef _FILE_H_
#define _FILE_H_

#include "simtypes.h"

#define FILE_LOG_CORE "simcore.log"

/* XML history file */
#define FILE_DIRECTORY_HISTORY "history" FILE_DIRECTORY_SLASH
#define FILE_EXTENSION_HISTORY ".html"

#ifndef _WIN32
#define FILE_DIRECTORY_SLASH "/"
void *sim_file_fopen_utf (const char *filename, const char *mode);
#define sim_file_fopen(filename, mode) sim_file_fopen_utf (filename, mode)
#define sim_file_close close
#else
#define FILE_DIRECTORY_SLASH "\\"
void *sim_file_fopen_utf (const char *filename, const unsigned short *mode);
#define sim_file_fopen(filename, MODE) sim_file_fopen_utf (filename, L##MODE)
#define sim_file_close _close
#endif

/* manipulate files with UTF-8 file names */
int sim_file_rename (const char *oldname, const char *newname);
int sim_file_remove (const char *filename);
int sim_file_mkdir (const char *filename);
int sim_file_size (const char *filename, simnumber *size, simunsigned *datetime);
int sim_file_open (const char *filename, int bits);

/* read and write bytes from file descriptor */
int sim_file_read (int fd, void *buffer, unsigned length);
int sim_file_write (int fd, const void *buffer, unsigned length);

/* directory for sim_file_new_name */
#define FILE_DIRECTORY_LOGIN (-1)
#define FILE_DIRECTORY_APP 0
#define FILE_DIRECTORY_USER 1

/* return name of file in login/user directory or in application home directory or nil if no home */
simtype sim_file_new_name (const char *filename, int directory);

/* set location and key for encryption and decryption of files in user directory */
const char *file_set_user (const char *user);
simtype file_set_password (simtype key, simbool password); /* consumes key unless nil */

/* return 0 if auto-login, 1 if password login, -1 if seed not available */
int file_check_password (void);

/* check if file exists in user directory */
simbool sim_file_check_exists (const char *filename);

/* flags for sim_file_create */
#define FILE_BIT_READ 1
#define FILE_BIT_WRITE 2
#define FILE_BIT_TEXT 4
#define FILE_BIT_APPEND 8
#define FILE_BIT_CREATE 16
#define FILE_BIT_TRUNCATE 32

/* create a file in user directory and open it with the specified mode. return file descriptor.
   also creates parent directories if not already created */
int sim_file_create (const char *filename, int bits);

/* truncate a file to its current position */
int sim_file_truncate (int fd);

/* securely remove file outside user directory; .old file is not removed */
int sim_file_wipe (const char *filename);

/* copy file inside user directory */
int file_copy (const char *oldfilename, const char *newfilename);

/* lock or unlock files in user directory */
int file_lock (simbool lock);

/* type for file_save and file_load */
#define FILE_TYPE_PLAINTEXT 0 /* not encrypted */
#define FILE_TYPE_KEY 1       /* encrypted with password */
#define FILE_TYPE_ENCRYPTED 2 /* encrypted */
#define FILE_TYPE_TEMPORARY 4 /* do not save backup file */

/* save file to user directory. use nil table to delete the file securely. type is FILE_TYPE_xxx */
int file_save (simtype table, const char *filename, int type);

/* load file from user directory */
int _file_load (const char *filename, int type, simtype *table, const char *file, unsigned line);
#define file_load(filename, type, table) _file_load (filename, type, table, __FUNCTION__, __LINE__)

/* load new DHT nodes from .torrent files */
void file_load_torrents (simtype mainline);

/* load last number of lines from log file into log buffer */
int sim_file_load_log (simnumber lines, unsigned maxsize);

/* internally used. maxsize is a memory limit in bytes (0 = unlimited) */
int sim_file_load_history (const char *filename, simnumber lines, unsigned maxsize, const char *nick,
                           simtype *messages, unsigned *count);

/* load last number of messages from history file into buffer. clear buffer if lines is zero */
int file_load_msg_ (simcontact contact, simnumber lines);

/* convert string to 64-bit unsigned decimal. return false if string is invalid */
simbool sim_convert_string_to_simunsigned (const char *string, simnumber *number);

/* debug logging */
void file_log_password (const char *module, int level, simbool numeric);

#endif
