#ifndef DV_IO_HPP
#define DV_IO_HPP

#include "../../include/dv-sdk/data/types.hpp"
#include "../../include/dv-sdk/module.hpp"
#include "../../include/dv-sdk/utils.h"

#include "FileDataTable.hpp"
#include "IOHeader.hpp"

#include <boost/algorithm/string.hpp>
#include <dv-processing/io/support/utils.hpp>

#include <lz4.h>
#include <lz4frame.h>
#include <lz4hc.h>
#include <zstd.h>

#ifndef LZ4F_HEADER_SIZE_MAX
#	define LZ4F_HEADER_SIZE_MAX 19
#endif

#ifndef ZSTD_CLEVEL_DEFAULT
#	define ZSTD_CLEVEL_DEFAULT 3
#endif

namespace dv {

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static constexpr LZ4F_preferences_t lz4CompressionPreferences = {
	{LZ4F_max64KB, LZ4F_blockLinked, LZ4F_noContentChecksum, LZ4F_frame},
	0, /* compression level; 0 == default fast level */
	0, /* autoflush */
};

static constexpr LZ4F_preferences_t lz4HighCompressionPreferences = {
	{LZ4F_max64KB, LZ4F_blockLinked, LZ4F_noContentChecksum, LZ4F_frame},
	9, /* compression level; 9 == default HC level */
	0, /* autoflush */
};
#pragma GCC diagnostic pop

static constexpr size_t lz4CompressionChunkSize = 64 * 1024;

struct lz4CompressionSupport {
	std::shared_ptr<struct LZ4F_cctx_s> context;
	const LZ4F_preferences_t *prefs;
	size_t chunkSize;
	size_t endSize;
};

struct lz4DecompressionSupport {
	std::shared_ptr<struct LZ4F_dctx_s> context;
};

struct zstdCompressionSupport {
	std::shared_ptr<struct ZSTD_CCtx_s> context;
	int level;
};

struct zstdDecompressionSupport {
	std::shared_ptr<struct ZSTD_DCtx_s> context;
};

static inline CompressionType parseCompressionTypeFromString(const std::string &str) {
	// Convert to upper-case to ensure valid comparison with enum names.
	const auto upperStr = boost::to_upper_copy(str);

	for (size_t i = 0; EnumNamesCompressionType()[i] != nullptr; i++) {
		if (upperStr == EnumNamesCompressionType()[i]) {
			return (EnumValuesCompressionType()[i]);
		}
	}

	return (CompressionType::NONE);
}

} // namespace dv

#endif // DV_IO_HPP
