using System;
using System.Runtime.InteropServices;

static class Program
{
    [StructLayout(LayoutKind.Sequential)]
    struct Image
    {
        public IntPtr data;
        public int width;
        public int height;
        public int mipmaps;
        public int format;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct Texture2D
    {
        public uint id;
        public int width;
        public int height;
        public int mipmaps;
        public int format;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct Vector2
    {
        public float x;
        public float y;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct Color
    {
        public byte r;
        public byte g;
        public byte b;
        public byte a;
    }

    private const string RAYLIB = "../_raylib-5.5_linux_amd64/lib/libraylib.so";

    [DllImport(RAYLIB)] private static extern void InitWindow(int width, int height, string title);
    [DllImport(RAYLIB)] private static extern void CloseWindow();

    [DllImport(RAYLIB)] private static extern void SetTargetFPS(int fps);
    [DllImport(RAYLIB)] private static extern void SetRandomSeed(uint seed);
    [DllImport(RAYLIB)] private static extern int GetRandomValue(int min, int max);

    [DllImport(RAYLIB)] private static extern Image LoadImage(string file_name);
    [DllImport(RAYLIB)] private static extern void ImageResize(ref Image image, int new_width, int new_height);
    [DllImport(RAYLIB)] private static extern Texture2D LoadTextureFromImage(Image image);
    [DllImport(RAYLIB)] private static extern void UnloadImage(Image image);
    [DllImport(RAYLIB)] private static extern void UnloadTexture(Texture2D texture);

    [DllImport(RAYLIB)] private static extern bool WindowShouldClose();
    [DllImport(RAYLIB)] private static extern float GetFrameTime();

    [DllImport(RAYLIB)] private static extern void BeginDrawing();
    [DllImport(RAYLIB)] private static extern void ClearBackground(Color color);
    [DllImport(RAYLIB)] private static extern void DrawTextureV(Texture2D texture, Vector2 position, Color tint);
    [DllImport(RAYLIB)] private static extern void EndDrawing();

    private const int WINDOW_WIDTH = 800;
    private const int WINDOW_HEIGHT = 600;
    private const int LOGO_HEIGHT = 64;
    private const float LOGO_SPEED = 300;

    private static Color BLACK = new Color() { r = 0, g = 0, b = 0, a = 255 };
    private static Color WHITE = new Color() { r = 255, g = 255, b = 255, a = 255 };

    public static void Main()
    {
        InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Raylib in C#");
        SetTargetFPS(60);

        Image logo_image = LoadImage("./csharp_logo.png");
        ImageResize(ref logo_image, logo_image.width * LOGO_HEIGHT / logo_image.height, LOGO_HEIGHT);
        Texture2D logo_texture = LoadTextureFromImage(logo_image);
        UnloadImage(logo_image);

        float x = GetRandomValue(0, WINDOW_WIDTH - logo_texture.width);
        float y = GetRandomValue(0, WINDOW_HEIGHT - logo_texture.height);

        float dx = LOGO_SPEED * (GetRandomValue(0, 1) == 1 ? -1 : 1);
        float dy = LOGO_SPEED * (GetRandomValue(0, 1) == 1 ? -1 : 1);

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

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

            if (x < 0 || (x + logo_texture.width) >= WINDOW_WIDTH - 1)
            {
                dx *= -1;
                x += dx * delta_time;
            }
            if (y < 0 || (y + logo_texture.height) >= WINDOW_HEIGHT - 1)
            {
                dy *= -1;
                y += dy * delta_time;
            }

            BeginDrawing();

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

            EndDrawing();
        }

        UnloadTexture(logo_texture);
        CloseWindow();
    }
}
