#include <gear/graphics/renderer.h>
#include <gear/camera.h>
#include <gear/ui/gui.h>
#include <gear/ui/console.h>

#include <sokol/sokol_app.h>
#include <sokol/sokol_gfx.h>
#include <sokol/sokol_log.h>
#include <sokol/sokol_glue.h>

#include <log.c/log.h>

g_renderer* renderer;
g_camera* camera;
g_gui* gui;

struct nk_font* font;

void init() {
    sg_setup(&(sg_desc){
        .environment = sglue_environment(),
        .logger.func = slog_func,
    });
    log_info("Sokol graphics initialized successfully");

    renderer = g_renderer_create(G_CYAN);
    gui = g_gui_create();
    camera = g_camera_create(HMM_V3(0.0f, 0.0f, -3.0f), HMM_V3(0.0f, 0.0f, 0.0f), 70.0f);
    log_info("GUI Layers (%d):", gui->layers.size);
    for(sl_vec_it(layer, gui->layers)) {
        log_info("    %s", (*layer)->name);
    }

    struct nk_font_atlas* atlas = calloc(1, sizeof(struct nk_font_atlas));
    nk_font_atlas_init_default(atlas);
    nk_font_atlas_begin(atlas);

    float font_size = 22.0f;
    const char* font_path = "assets/OpenSans-Regular.ttf";
    struct nk_font_config config = nk_font_config(font_size);

    font = nk_font_atlas_add_from_file(atlas, font_path, font_size, &config);

    const void *image;
    int atlas_width, atlas_height;
    image = nk_font_atlas_bake(atlas, &atlas_width, &atlas_height, NK_FONT_ATLAS_RGBA32);

    sg_image_desc img_desc = {0};
    img_desc.width = atlas_width;
    img_desc.height = atlas_height;
    img_desc.data.subimage[0][0].ptr = image;
    img_desc.data.subimage[0][0].size = atlas_width * atlas_height * 4;
    img_desc.pixel_format = SG_PIXELFORMAT_RGBA8;

    sg_image font_image = sg_make_image(&img_desc);
    sg_sampler samp = sg_make_sampler(&(sg_sampler_desc){ 0 });

    snk_image_t snk_img = snk_make_image(&(snk_image_desc_t){
        .image = font_image,
        .sampler = samp
    });

    // Complete the font atlas setup
    nk_font_atlas_end(atlas, snk_nkhandle(snk_img), NULL);
}

void frame() {
    g_gui_update(gui);
    nk_style_set_font(gui->ctx, &font->handle);

    g_renderer_begin(renderer);
    g_gui_render(sapp_width(), sapp_height());
    g_renderer_end(renderer);
}

void cleanup() {
    g_renderer_destroy(renderer);
    g_gui_destroy(gui);
    g_camera_destroy(camera);

    sg_shutdown();
}

void input(const sapp_event* event) {
    snk_handle_event(event);
}

sapp_desc sokol_main(int argc, char* argv[]) {
    (void)argc; (void)argv;
    FILE* log_fd = fopen("log.txt", "w");
    log_add_fp(log_fd, LOG_TRACE);

    log_info("Command line arguments (%d):", argc);
    for(i32 i = 0; i < argc; i++) {
        log_info("    %s", argv[i]);
    }

    return (sapp_desc){
        .init_cb = init,
        .frame_cb = frame,
        .cleanup_cb = cleanup,
        .event_cb = input,
        .width = 640,
        .height = 480,
        .window_title = "Gear",
        .icon.sokol_default = true,
        .logger.func = slog_func,
        .swap_interval = 0
    };
}
