#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define NOB_REALLOC realloc
#define NOB_ASSERT assert

// Initial capacity of a dynamic array
#define NOB_DA_INIT_CAP 256

// Append an item to a dynamic array
#define nob_da_append(da, item)                                                          \
    do {                                                                                 \
        if ((da)->count >= (da)->capacity) {                                             \
            (da)->capacity = (da)->capacity == 0 ? NOB_DA_INIT_CAP : (da)->capacity*2;   \
            (da)->items = NOB_REALLOC((da)->items, (da)->capacity*sizeof(*(da)->items)); \
            NOB_ASSERT((da)->items != NULL && "Buy more RAM lol");                       \
        }                                                                                \
                                                                                         \
        (da)->items[(da)->count++] = (item);                                             \
    } while (0)

#include "raylib.h"
#include "raymath.h"

#define PLAYER_SPEED 1000
#define REAL_FPS 30
#define TARGET_FPS 480
#define TARGET_DT (1.0/TARGET_FPS)
#define GRAVITY 1000.0f
#define COLLISION_DAMPING 0.8

typedef struct {
    Vector2 *items;
    size_t count;
    size_t capacity;
} Vector2s;

typedef struct {
    Color *items;
    size_t count;
    size_t capacity;
} Colors;

Texture tex_rac;

int win_fun()
{
    SetWindowState(FLAG_WINDOW_RESIZABLE);
#ifdef RELEASE
    ShowCursor();
    EnableCursor();
#endif
#ifdef RELEASE
    SetWindowSize(690, 690);
#else
    SetWindowSize(1600, 900);
#endif
    SetTargetFPS(REAL_FPS);
    Vector2s positions = {0};
    Vector2s velocities = {0};
    Colors colors = {0};
#ifdef RELEASE
#include "assets/raccon-delicieu.h"
    Image img_rac = LoadImageFromMemory(".png", raccoon_data, raccoon_size);
    tex_rac = LoadTextureFromImage(img_rac);
#else
    tex_rac = LoadTexture("assets/raccon-delicieu.png");
#endif
    Vector2 prev_winpos = GetWindowPosition();
    while (!WindowShouldClose()) {
        Vector2 winpos = GetWindowPosition();
        Vector2 dwinpos = Vector2Subtract(winpos, prev_winpos);
        float w = GetScreenWidth();
        float h = GetScreenHeight();
        float real_dt = GetFrameTime();
        float radius = 40.0f;

        BeginDrawing();
            ClearBackground(GetColor(0x181818FF));

            if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
                nob_da_append(&positions, GetMousePosition());
                float angle = DEG2RAD*GetRandomValue(0, 360);
                Vector2 dir = {500*cosf(angle), 500*sinf(angle)};
                nob_da_append(&velocities, dir);
                nob_da_append(&colors, ColorFromHSV(GetRandomValue(0, 360), 1, 1));
            }

            for (float t = 0.0; t < real_dt; t += TARGET_DT) {
                for (size_t i = 0; i < positions.count; ++i) {
                    float f = t/real_dt;

                    positions.items[i] = Vector2Subtract(positions.items[i], Vector2Scale(dwinpos, TARGET_DT/real_dt));
                    velocities.items[i].y += GRAVITY*TARGET_DT;

                    float nx = positions.items[i].x + velocities.items[i].x*TARGET_DT;
                    if (nx - radius <= 0) {
                        positions.items[i].x = radius;
                        velocities.items[i].x *= -COLLISION_DAMPING;
                        velocities.items[i].x += dwinpos.x*TARGET_DT/real_dt*300;
                    } else if (nx + radius >= w) {
                        positions.items[i].x = w - radius;
                        velocities.items[i].x *= -COLLISION_DAMPING;
                        velocities.items[i].x += dwinpos.x*TARGET_DT/real_dt*300;
                    } else {
                        positions.items[i].x = nx;
                    }

                    float ny = positions.items[i].y + velocities.items[i].y*TARGET_DT;
                    if (ny - radius <= 0) {
                        positions.items[i].y = radius;
                        velocities.items[i].y *= -COLLISION_DAMPING;
                        velocities.items[i].y += dwinpos.y*TARGET_DT/real_dt*300;
                    } else if (ny + radius >= h) {
                        positions.items[i].y = h - radius;
                        velocities.items[i].y *= -COLLISION_DAMPING;
                        velocities.items[i].y += dwinpos.y*TARGET_DT/real_dt*300;
                    } else {
                        positions.items[i].y = ny;
                    }

                    // DrawRing(positions.items[i], radius*0.8, radius, 0, 360, 100, ColorAlpha(colors.items[i], f));
                    DrawTexturePro(
                        tex_rac,
                        (Rectangle) {0, 0, tex_rac.width, tex_rac.height},
                        (Rectangle) {positions.items[i].x-radius, positions.items[i].y-radius, radius*2, radius*2},
                        (Vector2) {0, 0},
                        0.0f,
                        ColorAlpha(colors.items[i], f)
                    );
                }
            }

        EndDrawing();

        prev_winpos = winpos;
    }
    CloseWindow();
    return 0;
}
