use std::{
    ffi::{c_float, c_int, c_uchar, c_uint},
    time::{SystemTime, UNIX_EPOCH},
};

extern "C" {
    fn InitWindow(width: c_int, height: c_int, title: *const u8);
    fn CloseWindow();

    fn SetTargetFPS(fps: c_int);
    fn SetRandomSeed(seed: c_uint);
    fn GetRandomValue(min: c_int, max: c_int) -> c_int;

    fn LoadTexture(file_name: *const u8) -> Texture2D;
    fn UnloadTexture(texture: Texture2D);

    fn WindowShouldClose() -> bool;
    fn GetFrameTime() -> c_float;

    fn BeginDrawing();
    fn ClearBackground(color: Color);
    fn DrawTextureEx(
        texture: Texture2D,
        position: Vector2,
        rotation: c_float,
        scale: c_float,
        tint: Color,
    );
    fn EndDrawing();
}

#[derive(Clone, Copy)]
#[repr(C)]
struct Texture2D {
    id: c_uint,
    width: c_int,
    height: c_int,
    mipmaps: c_int,
    format: c_int,
}

#[repr(C)]
struct Vector2 {
    x: c_float,
    y: c_float,
}

#[repr(C)]
struct Color {
    r: c_uchar,
    g: c_uchar,
    b: c_uchar,
    a: c_uchar,
}

const WINDOW_WIDTH: c_int = 800;
const WINDOW_HEIGHT: c_int = 600;
const LOGO_SCALE: f32 = 0.04;
const LOGO_SPEED: f32 = 300.0;

const BLACK: Color = Color {
    r: 0,
    g: 0,
    b: 0,
    a: 255,
};
const WHITE: Color = Color {
    r: 255,
    g: 255,
    b: 255,
    a: 255,
};

fn main() {
    unsafe {
        InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Raylib in Rust".as_ptr());
        SetTargetFPS(60);
        SetRandomSeed(
            SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs() as u32,
        );

        let logo_texture = LoadTexture("./rust_logo.png".as_ptr());

        let logo_width = (logo_texture.width as f32 * LOGO_SCALE) as i32;
        let logo_height = (logo_texture.height as f32 * LOGO_SCALE) as i32;

        let mut x = GetRandomValue(0, WINDOW_WIDTH - logo_width) as f32;
        let mut y = GetRandomValue(0, WINDOW_HEIGHT - logo_height) as f32;

        let mut dx = LOGO_SPEED * if GetRandomValue(0, 1) == 1 { -1.0 } else { 1.0 };
        let mut dy = LOGO_SPEED * if GetRandomValue(0, 1) == 1 { -1.0 } else { 1.0 };

        while !WindowShouldClose() {
            let delta_time = GetFrameTime();

            x += dx * delta_time;
            y += dy * delta_time;

            if x < 0.0 || x + logo_width as f32 >= WINDOW_WIDTH as f32 - 1.0 {
                dx *= -1.0;
                x += dx * delta_time;
            }
            if y < 0.0 || y + logo_height as f32 >= WINDOW_HEIGHT as f32 - 1.0 {
                dy *= -1.0;
                y += dy * delta_time;
            }

            BeginDrawing();

            ClearBackground(BLACK);
            DrawTextureEx(logo_texture, Vector2 { x, y }, 0.0, LOGO_SCALE, WHITE);

            EndDrawing();
        }

        UnloadTexture(logo_texture);
        CloseWindow();
    }
}
