#ifndef LANDER_LOG
#define LANDER_LOG

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

extern const char *log_level_names[];

typedef enum log_level {
  log_level_debug = 0,
  log_level_info = 1,
  log_level_warning = 2,
  log_level_error = 3,
  log_level_critical = 4,
} log_level;

extern log_level _log_level;

void _lander_log(log_level level, FILE *f, const char *fmt, ...);

#define log_level(level) _log_level = level

#define flog(level, f, ...) _lander_log(level, f, __VA_ARGS__)
#define log(level, ...) _lander_log(level, NULL, __VA_ARGS__)
#define debug(...) _lander_log(log_level_debug, NULL, __VA_ARGS__)
#define fdebug(f, ...) _lander_log(log_level_debug, f, __VA_ARGS__)
#define info(...) _lander_log(log_level_info, NULL, __VA_ARGS__)
#define finfo(f, ...) _lander_log(log_level_info, f, __VA_ARGS__)
#define warning(...) _lander_log(log_level_warning, NULL, __VA_ARGS__)
#define fwarning(f, ...) _lander_log(log_level_warning, f, __VA_ARGS__)
#define error(...) _lander_log(log_level_error, NULL, __VA_ARGS__)
#define ferror(f, ...) _lander_log(log_level_error, f, __VA_ARGS__)
#define critical(status, ...)                                                  \
  _lander_log(log_level_critical, NULL, __VA_ARGS__);                          \
  exit(status)
#define fcritical(status, f, ...)                                              \
  _lander_log(log_level_critical, f, __VA_ARGS__);                             \
  exit(status)

#endif