{.passC:"-DBC7ENC_USE_MINIZ=0".}
{.compile:"./bc7enc_rdo/bc7decomp.cpp",
compile:"./bc7enc_rdo/bc7decomp_ref.cpp",
compile:"./bc7enc_rdo/bc7enc.cpp",
compile:"./bc7enc_rdo/ert.cpp",
compile:"./bc7enc_rdo/lodepng.cpp",
compile:"./bc7enc_rdo/rdo_bc_encoder.cpp",
compile:"./bc7enc_rdo/rgbcx.cpp",
compile:"./bc7enc_rdo/utils.cpp",
compile:"./bc7enc.cpp".}

##  Valid formats: 1 3 4 5 7
##  BC1 RGB    4bpp   fast, small
##  BC3 RGBA   8bpp   fast
##  BC4 gray   4bpp   best for grayscale
##  BC5 X+Y    8bpp
##  BC7 RGB(A) 8bpp   slow, best quality

type EncodeBcInput* {.bycopy.} = object
    data*: pointer
    len*: int32
    width*: int32
    height*: int32
    format*: int8 ##  BCn format to use.
    bc1_quality*: int8 ## between 0 and 18
    bc7_quality*: int8 ## between 0 and 6

type EncodeBcOutput* {.bycopy.} = object
    data*: pointer
    len*: int32
    row_len*: int32

type EncodeBcError* {.size:4.} = enum
    NO_ERROR = 0, ENCODER_INIT_ERROR = 1, ENCODE_ERROR = 2,
    INVALID_SIZE_ERROR = 3, UNSUPPORTED_FORMAT_ERROR = 4,
    INVALID_INPUT_LENGTH_ERROR = 5, INVALID_OUTPUT_LENGTH_ERROR = 6,
    INVALID_SETTINGS = 7,

proc encode_bc*(input: var EncodeBcInput, output: var EncodeBcOutput, verbose: bool): EncodeBcError {.importc, cdecl.}

{.hint[XDeclaredButNotUsed]: off.}

# S3TC (BC1-3)
const GL_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0'i32
const GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1'i32
const GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2'i32
const GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3'i32
# S3TC (BC1-3) sRGB
const GL_COMPRESSED_SRGB_S3TC_DXT1_EXT = 0x8C4C'i32
const GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT = 0x8C4D'i32
const GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT = 0x8C4E'i32
const GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT = 0x8C4F'i32
# RGTC (BC4-5)
const GL_COMPRESSED_RED_RGTC1_EXT = 0x8DBB'i32
const GL_COMPRESSED_SIGNED_RED_RGTC1_EXT = 0x8DBC'i32
const GL_COMPRESSED_RED_GREEN_RGTC2_EXT = 0x8DBD'i32
const GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT = 0x8DBE'i32
# BPTC float (BC6H)
const GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB = 0x8E8E'i32
const GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB = 0x8E8F'i32
# BPTC (BC7)
const GL_COMPRESSED_RGBA_BPTC_UNORM_ARB = 0x8E8C'i32
# BPTC (BC7) sRGB
const GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB = 0x8E8D'i32

func get_bc_bpp_internal_format*(bc_format: int8, is_sRGB: bool): (int8, int32) =
    let (bpp, internal_format) = if is_sRGB:
        case bc_format:
            of 1: (4, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT)
            of 2: (8, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT)
            of 3: (8, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
            of 4: (4, GL_COMPRESSED_RED_RGTC1_EXT) # sRGB is ignored
            of 5: (8, GL_COMPRESSED_RED_GREEN_RGTC2_EXT) # sRGB is ignored
            of 6: (8, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB) # sRGB is ignored
            of 7: (8, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB)
            else: (0, 0'i32)
    else:
        case bc_format:
            of 1: (4, GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
            of 2: (8, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)
            of 3: (8, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
            of 4: (4, GL_COMPRESSED_RED_RGTC1_EXT)
            of 5: (8, GL_COMPRESSED_RED_GREEN_RGTC2_EXT)
            of 6: (8, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB)
            of 7: (8, GL_COMPRESSED_RGBA_BPTC_UNORM_ARB)
            else: (0, 0'i32)
    assert bpp != 0, "Invalid bc_format " & $bc_format
    return (bpp.int8, internal_format)