#pragma once
#include <cstdint>
#include <stdexcept>
#include <string>
#include <vector>

namespace bmp2tile
{

struct Color
{
    uint8_t R = 0, G = 0, B = 0;

    bool operator==(const Color& o) const
    {
        return R == o.R && G == o.G && B == o.B;
    }
};

// An image with an explicit palette (<=256 colours) and one palette-index
// byte per pixel. This -- not RGB pixels -- is the representation the rest
// of bmp2tile operates on, because the whole point of the original tool is
// that *you* control which palette index each pixel maps to.
struct IndexedImage
{
    int Width = 0;
    int Height = 0;
    std::vector<Color> Palette;   // Palette.size() <= 256
    std::vector<uint8_t> Pixels;  // Width*Height entries, row-major, top-to-bottom

    uint8_t At(int x, int y) const
    {
        return Pixels[static_cast<size_t>(y) * Width + x];
    }
};

// Thrown by LoadImage() for anything it can't turn into a usable
// IndexedImage: bad file, unsupported BMP variant, too many colours, etc.
class ImageLoadError : public std::runtime_error
{
public:
    explicit ImageLoadError(const std::string& message) : std::runtime_error(message)
    {
    }
};

// Loads an image file into an IndexedImage.
//
//   - Indexed (1/4/8bpp, uncompressed) BMP files are decoded directly by a
//     small hand-written reader, which preserves the on-disk palette and
//     its order exactly -- this matters because bmp2tile relies on you
//     having arranged the palette deliberately.
//   - Everything else (PNG, GIF, 24/32bpp BMP) is decoded via stb_image to
//     RGBA8, then quantized by collecting distinct colours in first-seen
//     order. If the image contains more than maxColors distinct colours,
//     this throws ImageLoadError -- matching the original tool's "too many
//     colours, won't process it" behaviour. Because this path derives the
//     palette from pixel order rather than an embedded palette table, its
//     palette order is not guaranteed to match what a paint program's
//     "palette" panel would show; use indexed BMP if palette order matters
//     to you (which, per the original tool's own advice, it should).
//   - PCX is not supported.
//
// maxColors should be 16 for a 4bpp image or 256 for 8bpp, matching the
// original tool's bit-depth options.
IndexedImage LoadImage(const std::string& path, int maxColors = 16);

}  // namespace bmp2tile
