/**
 * @file image_manips.hpp
 * @author GRY Nicolas (nicolas.gry@inria.fr)
 * @brief
 * @version 0.1
 * @date 2026-08-05
 *
 * @copyright Copyright (c) 2026
 *
 * @details
 */
#pragma once

#include <cstdint>
#include <string>
#include <vector>

#if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
    defined(__MINGW32__) || defined(__BORLANDC__)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif

enum class Channel { Red, Green, Blue };

using RGBImage = std::vector<std::vector<std::vector<uint8_t>>>;
using BWImage  = std::vector<std::vector<uint8_t>>;

/**
 * @brief Reads a grayscale image from a file.
 *
 * @param filename Path to the image file.
 * @return A BWImage structure containing the pixel data.
 */
EXPORT
BWImage read_bw_image(const std::string filename);

/**
 * @brief Reads an RGB image from a file.
 *
 * @param filename Path to the image file.
 * @return An RGBImage containing the pixel data (R, G, B).
 */
EXPORT
RGBImage read_rgb_image(const std::string filename);

/**
 * @brief Writes a grayscale image to a PNG file.
 *
 * @param filename Path to save the image.
 * @param image The BWImage object containing the data.
 */
EXPORT
void write_bw_image(const std::string filename, const BWImage& image);

/**
 * @brief Writes an RGB image to a PNG file.
 *
 * @param filename Path to save the image.
 * @param image The RGBImage object containing the data.
 */
EXPORT
void write_rgb_image(const std::string filename, const RGBImage& image);

/**
 * @brief Swaps the values between two specified color channels in an RGB image.
 *
 * Modifies the input image structure by swapping all R/G/B values
 * for every pixel between c1 and c2. The input image isn't modified in placed.
 *
 * @param image The RGBImage to modify.
 * @param c1 The first channel to swap.
 * @param c2 The second channel to swap.
 * @return An RGBImage containing the pixel data .
 */
EXPORT
RGBImage swap_channels(const RGBImage& image, Channel c1, Channel c2);

/**
 * @brief Converts an RGBImage to a BWImage by averaging the R, G, and B
 * channels.
 *
 * Each pixel in the resulting BWImage holds the arithmetic mean of its RGB
 * components.
 *
 * @param rgb_image The input RGB image.
 * @return A new BWImage containing the calculated grayscale data.
 */
EXPORT
BWImage convert_rgb_to_bw(const RGBImage& rgb_image);