#pragma once

#include "pxl8_types.h"

#ifdef __cplusplus
extern "C" {
#endif

extern const u8 PXL8_BAYER_4X4[16];

static inline i8 pxl8_bayer_offset(u32 x, u32 y) {
    return (i8)(PXL8_BAYER_4X4[(y & 3) * 4 + (x & 3)]) - 8;
}

static inline u8 pxl8_ordered_dither(u8 value, u32 x, u32 y) {
    u8 bayer = PXL8_BAYER_4X4[(y & 3) * 4 + (x & 3)];
    u16 result = (u16)value + (bayer >> 1);
    return result > 255 ? 255 : (u8)result;
}

static inline u8 pxl8_dither_light(u8 light, u32 x, u32 y) {
    i8 offset = pxl8_bayer_offset(x, y) >> 1;
    i16 result = (i16)light + offset;
    if (result < 0) return 0;
    if (result > 255) return 255;
    return (u8)result;
}

static inline u8 pxl8_dither_float(f32 value, u32 x, u32 y) {
    u8 floor_val = (u8)value;
    f32 frac = value - (f32)floor_val;
    f32 threshold = (PXL8_BAYER_4X4[(y & 3) * 4 + (x & 3)] + 0.5f) * (1.0f / 16.0f);
    if (frac > threshold) {
        return floor_val < 255 ? floor_val + 1 : 255;
    }
    return floor_val;
}

#ifdef __cplusplus
}
#endif
