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

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

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

    fn LoadImage(file_name: *const c_char) -> Image;
    fn ImageResize(image: *mut Image, new_width: c_int, new_height: c_int);
    fn LoadTextureFromImage(image: Image) -> Texture2D;
    fn UnloadImage(image: Image);
    fn UnloadTexture(texture: Texture2D);

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

    fn BeginDrawing();
    fn ClearBackground(color: Color);
    fn DrawTextureV(texture: Texture2D, position: Vector2, tint: Color);
    fn EndDrawing();
}

#[derive(Clone, Copy)]
#[repr(C)]
struct Image {
    data: *mut c_void,
    width: c_int,
    height: c_int,
    mipmaps: c_int,
    format: c_int,
}

#[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_HEIGHT: c_int = 64;
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, c"Raylib in Rust".as_ptr());
        SetTargetFPS(60);
        SetRandomSeed(
            SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs() as u32,
        );

        let mut logo_image = LoadImage(c"./rust_logo.png".as_ptr());
        ImageResize(
            &mut logo_image,
            logo_image.width * LOGO_HEIGHT / logo_image.height,
            LOGO_HEIGHT,
        );
        let logo_texture = LoadTextureFromImage(logo_image);
        UnloadImage(logo_image);

        let mut x = GetRandomValue(0, WINDOW_WIDTH - logo_texture.width) as f32;
        let mut y = GetRandomValue(0, WINDOW_HEIGHT - logo_texture.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_texture.width as f32 >= WINDOW_WIDTH as f32 - 1.0 {
                dx *= -1.0;
                x += dx * delta_time;
            }
            if y < 0.0 || y + logo_texture.height as f32 >= WINDOW_HEIGHT as f32 - 1.0 {
                dy *= -1.0;
                y += dy * delta_time;
            }

            BeginDrawing();

            ClearBackground(BLACK);
            DrawTextureV(logo_texture, Vector2 { x, y }, WHITE);

            EndDrawing();
        }

        UnloadTexture(logo_texture);
        CloseWindow();
    }
}
