#include <shaders.h>
#include <stdarg.h>
#include <slibs.h>
#include <opengl.h>

uint32_t compile_shader(const char* path, int32_t type) {
    sl_string source = { 0 };
    sl_read_file(path, &source);
    const char* source_cstr = sl_c_str(source);

    uint32_t id = compile_shader_text(path, source_cstr, type);

    sl_str_free(source); 

    return id;
}

uint32_t compile_shader_text(const char* name, const char* text, int32_t type) {
    uint32_t id = glCreateShader(type);
    glShaderSource(id, 1, &text, NULL);
    glCompileShader(id);

    int success;
    char info_log[512];
    glGetShaderiv(id, GL_COMPILE_STATUS, &success);
    if(!success) {
        glGetShaderInfoLog(id, 512, NULL, info_log);
        printf("[Shader %d, %s] Failed to compile: %s\n", id, name, info_log);
        exit(-1);
    } else {
        printf("[Shader %d, %s] Compiled successfully\n", id, name);
    }

    return id;
}


uint32_t load_shader_program(uint32_t shader, ...) {
    sl_vec(uint32_t) shaders = { 0 };

    va_list args;
    va_start(args, shader);
    while(shader != 0) {
        sl_vec_push(shaders, shader);
        shader = va_arg(args, uint32_t);
    }
    va_end(args);

    uint32_t program = glCreateProgram();
    for(sl_vec_it(shader, shaders)) {
        glAttachShader(program, *shader);
        printf("[Shader %d] Attached to program %d\n", *shader, program);
    }
    glLinkProgram(program);

    int success;
    char info_log[512];
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    if(!success) {
        glGetProgramInfoLog(program, 512, NULL, info_log);
        printf("[Program %d] Failed to link: %s\n", program, info_log);
        exit(-1);
    } else {
        printf("[Program %d] Linked successfully\n", program);
    }

    for(sl_vec_it(shader, shaders)) {
        glDeleteShader(*shader);
        printf("[Shader %d] Deleted successfully\n", *shader);
    } 

    return program;
}
