#ifndef PROTOTYPE1_SRC_L2_MARIE_TEXTURE_PROCESSING_H
#define PROTOTYPE1_SRC_L2_MARIE_TEXTURE_PROCESSING_H

#include "../../../gen/l1/pixel_masses.h"
#include "rasterization.h"

/* Fixes several of my generated textures */
NODISCARD TextureDataR8G8B8A8 TextureDataR8G8B8A8_expand_nontransparent_1px(const TextureDataR8G8B8A8* self) {
    S32 width = (S32)self->width;
    S32 height = (S32)self->height;
    TextureDataR8G8B8A8 res = TextureDataR8G8B8A8_new(width, height);
    // S32 chain[9][2] = {{0, 0}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}};
    for (S32 y = 0; y < height; y++) {
        for (S32 x = 0; x < width;) {
            cvec4 p = *TextureDataR8G8B8A8_at(self, x, y);
            cvec4* r = TextureDataR8G8B8A8_mat(&res, x, y);
            if (p.w != 255) {
                for (S32 i = -1; i <= 1; i++) {
                    for (S32 j = -1; j <= 1; j++) {
                        S32 X = x + i, Y = y + i;
                        if (X < 0 || X >= width || Y < 0 || Y >= height || i == 0 || y == 0)
                            continue;
                        cvec4 n = *TextureDataR8G8B8A8_at(self, X, Y);
                        if (n.w == 255) {
                            *r = n;
                            goto done;
                        }
                    }
                }
            }
            *r = p;
            done:
            x++;
        }
    }
    return res;
}

vec4 marie_color_cvec4_to_vec4(cvec4 clr) {
    return (vec4){(float)clr.x / 255, (float)clr.y / 255, (float)clr.z / 255, (float)clr.w / 255};
}

cvec4 marie_color_vec4_to_cvec4(vec4 clr) {
    return (cvec4){(U8)roundf(clr.x * 255), (U8)roundf(clr.y * 255), (U8)roundf(clr.z * 255), (U8)roundf(clr.w * 255)};
}

vec3 marie_color_cvec3_to_vec3(cvec3 clr) {
    return (vec3){(float)clr.x / 255, (float)clr.y / 255, (float)clr.z / 255};
}

cvec3 marie_color_vec3_to_cvec3(vec3 clr) {
    return (cvec3){(U8)roundf(clr.x * 255), (U8)roundf(clr.y * 255), (U8)roundf(clr.z * 255)};
}

typedef struct {
    TextureDataR8G8B8A8* self;
    cvec4 pixel;
} TextureDataR8G8B8A8_draw_triangle_of_one_color_H_DrawGuest;

void TextureDataR8G8B8A8_draw_triangle_of_one_color_h_draw_guest(void* ug, S32 x, S32 y, vec4 attr) {
    TextureDataR8G8B8A8_draw_triangle_of_one_color_H_DrawGuest *g = ug;
    if (TextureDataR8G8B8A8_is_inside(g->self, x, y))
        *TextureDataR8G8B8A8_mat(g->self, x, y) = g->pixel;
}

/* Given triangle is not natural : it is from parameter space */
void TextureDataR8G8B8A8_draw_parametrized_triangle_of_one_color(
    TextureDataR8G8B8A8* self, vec3 color, MarieTriangle param_triang, mat3x2 trop
    ) {
    TextureDataR8G8B8A8_draw_triangle_of_one_color_H_DrawGuest aboba =
        { self, marie_color_vec4_to_cvec4(vec3_and_one(color)) };
    MarieTriangle natural = MarieTriangle_mat3x2_mul_pos(param_triang, trop);
    marie_rasterize_triangle_with_attr(
        (MariePlaneVertAttr){natural.v0, {}}, (MariePlaneVertAttr){natural.v1, {}}, (MariePlaneVertAttr){natural.v2, {}},
        (FnMarieRasterizerCallback){.fn = TextureDataR8G8B8A8_draw_triangle_of_one_color_h_draw_guest,
            .guest = &aboba});
}

void TextureDataR8G8B8A8_draw_triangle_of_one_color(TextureDataR8G8B8A8* self, vec3 color, MarieTriangle trig){
    TextureDataR8G8B8A8_draw_triangle_of_one_color_H_DrawGuest aboba =
    { self, marie_color_vec4_to_cvec4(vec3_and_one(color)) };
    marie_rasterize_triangle_with_attr(
        (MariePlaneVertAttr){trig.v0, {}}, (MariePlaneVertAttr){trig.v1, {}}, (MariePlaneVertAttr){trig.v2, {}},
        (FnMarieRasterizerCallback){.fn = TextureDataR8G8B8A8_draw_triangle_of_one_color_h_draw_guest,
            .guest = &aboba});
}

#endif