#ifndef _ERROR_UTILS
#define _ERROR_UTILS

#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>

// separator between user message and errno message
#define SEPARATOR ", "
#define BREAKLINE "\n"

/**
 * print error message
 */
void error(const char *sys_msg, va_list arg)
{
    char *errorTxt = strerror(errno);
    char errorNum[5];
    sprintf(errorNum, " (%d)", errno);

    FILE *fd = fopen("/dev/stderr", "w");

    // + 1 is due to strcpy on sys_msg which add \0 at the end of the string
    char *concatenated_msg = malloc(
        (sizeof(*(errorTxt)) * strlen(errorTxt)) +
        (sizeof(*(sys_msg)) * strlen(sys_msg) + 1) +
        strlen(SEPARATOR) +
        strlen(errorNum) +
        strlen(BREAKLINE));

    strcpy(concatenated_msg, sys_msg);
    strcat(concatenated_msg, SEPARATOR);
    strcat(concatenated_msg, errorTxt);
    strcat(concatenated_msg, errorNum);
    strcat(concatenated_msg, BREAKLINE);

    vfprintf(fd, concatenated_msg, arg);

    fclose(fd);
    free(concatenated_msg);
    va_end(arg);
}

/**
 * print error message and exit program with error
 */
void last_error(const char *sys_msg, va_list arg)
{
    error(sys_msg, arg);
    exit(EXIT_FAILURE);
}

#endif
