#ifndef KBDFILE_CONTEXTP_H
#define KBDFILE_CONTEXTP_H

#include <stdarg.h>

#include "kbdfile.h"
#include "nls.h"

/**
 * @brief Opaque object representing the library context.
 */
struct kbdfile_ctx {
	/**
	 * User defined logging function.
	 */
	kbdfile_logger_t log_fn;
	/**
	 * The data passed to the @ref log_fn logging function as the first argument.
	 */
	void *log_data;

	/**
	 * Logging priority used by @ref log_fn logging function.
	 */
	int log_priority;
};

struct kbdfile {
	struct kbdfile_ctx *ctx;
	int flags;
	FILE *fd;
	char pathname[MAXPATHLEN];
};

#define KBDFILE_CTX_INITIALIZED 0x01
#define KBDFILE_PIPE            0x02
#define KBDFILE_COMPRESSED      0x04

#define kbdfile_log_cond(ctx, level, arg...)                                          \
	do {                                                                     \
		if (ctx->log_priority >= level)                                  \
			kbdfile_log(ctx, level, __FILE__, __LINE__, __func__, ##arg); \
	} while (0)

/**
 * Wrapper to output debug-level messages
 * @param ctx is a kbdfile library context.
 * @param arg is output message.
 */
#define DBG(ctx, arg...) kbdfile_log_cond(ctx, LOG_DEBUG, ##arg)

/**
 * Wrapper to output informational messages
 * @param ctx is a kbdfile library context.
 * @param arg is output message.
 */
#define INFO(ctx, arg...) kbdfile_log_cond(ctx, LOG_INFO, ##arg)

/**
 * Wrapper to output warning conditions
 * @param ctx is a kbdfile library context.
 * @param arg is output message.
 */
#define WARN(ctx, arg...) kbdfile_log_cond(ctx, LOG_WARNING, ##arg)

/**
 * Wrapper to output error conditions
 * @param ctx is a kbdfile library context.
 * @param arg is output message.
 */
#define ERR(ctx, arg...) kbdfile_log_cond(ctx, LOG_ERR, ##arg)

char *kbd_strerror(int errnum, char *buf, size_t buflen);

static inline FILE *kbdfile_decompressor_dummy(struct kbdfile *file KBD_ATTR_UNUSED)
{
	return NULL;
}

#define kbdfile_decompressor_zlib	kbdfile_decompressor_dummy
#define kbdfile_decompressor_bzip2	kbdfile_decompressor_dummy
#define kbdfile_decompressor_lzma	kbdfile_decompressor_dummy
#define kbdfile_decompressor_zstd	kbdfile_decompressor_dummy

#ifdef HAVE_ZLIB
#undef kbdfile_decompressor_zlib
FILE  *kbdfile_decompressor_zlib(struct kbdfile *file) KBD_ATTR_MUST_CHECK;
#endif

#ifdef HAVE_BZIP2
#undef kbdfile_decompressor_bzip2
FILE  *kbdfile_decompressor_bzip2(struct kbdfile *file) KBD_ATTR_MUST_CHECK;
#endif

#ifdef HAVE_LZMA
#undef kbdfile_decompressor_lzma
FILE  *kbdfile_decompressor_lzma(struct kbdfile *file) KBD_ATTR_MUST_CHECK;
#endif

#ifdef HAVE_ZSTD
#undef kbdfile_decompressor_zstd
FILE  *kbdfile_decompressor_zstd(struct kbdfile *file) KBD_ATTR_MUST_CHECK;
#endif

#endif /* KBDFILE_CONTEXTP_H */
