// Re-export passthrough functions from internal FFI layer

///|
pub using @ffi {draw_grid}

// ============================================================================
// 3D shape drawing (wrappers)
// ============================================================================

///|
pub fn draw_line_3d(
  start_pos : Vector3,
  end_pos : Vector3,
  color : Color,
) -> Unit {
  @ffi.draw_line_3d(start_pos.to_bytes(), end_pos.to_bytes(), color.to_bytes())
}

///|
pub fn draw_point_3d(position : Vector3, color : Color) -> Unit {
  @ffi.draw_point_3d(position.to_bytes(), color.to_bytes())
}

///|
pub fn draw_circle_3d(
  center : Vector3,
  radius : Float,
  rot_axis : Vector3,
  rot_angle : Float,
  color : Color,
) -> Unit {
  @ffi.draw_circle_3d(
    center.to_bytes(),
    radius,
    rot_axis.to_bytes(),
    rot_angle,
    color.to_bytes(),
  )
}

///|
pub fn draw_cube(
  position : Vector3,
  width : Float,
  height : Float,
  length : Float,
  color : Color,
) -> Unit {
  @ffi.draw_cube(position.to_bytes(), width, height, length, color.to_bytes())
}

///|
pub fn draw_cube_v(position : Vector3, size : Vector3, color : Color) -> Unit {
  @ffi.draw_cube_v(position.to_bytes(), size.to_bytes(), color.to_bytes())
}

///|
pub fn draw_cube_wires(
  position : Vector3,
  width : Float,
  height : Float,
  length : Float,
  color : Color,
) -> Unit {
  @ffi.draw_cube_wires(
    position.to_bytes(),
    width,
    height,
    length,
    color.to_bytes(),
  )
}

///|
pub fn draw_cube_wires_v(
  position : Vector3,
  size : Vector3,
  color : Color,
) -> Unit {
  @ffi.draw_cube_wires_v(position.to_bytes(), size.to_bytes(), color.to_bytes())
}

///|
pub fn draw_sphere(center : Vector3, radius : Float, color : Color) -> Unit {
  @ffi.draw_sphere(center.to_bytes(), radius, color.to_bytes())
}

///|
pub fn draw_sphere_ex(
  center : Vector3,
  radius : Float,
  rings : Int,
  slices : Int,
  color : Color,
) -> Unit {
  @ffi.draw_sphere_ex(
    center.to_bytes(),
    radius,
    rings,
    slices,
    color.to_bytes(),
  )
}

///|
pub fn draw_sphere_wires(
  center : Vector3,
  radius : Float,
  rings : Int,
  slices : Int,
  color : Color,
) -> Unit {
  @ffi.draw_sphere_wires(
    center.to_bytes(),
    radius,
    rings,
    slices,
    color.to_bytes(),
  )
}

///|
pub fn draw_cylinder(
  position : Vector3,
  radius_top : Float,
  radius_bottom : Float,
  height : Float,
  slices : Int,
  color : Color,
) -> Unit {
  @ffi.draw_cylinder(
    position.to_bytes(),
    radius_top,
    radius_bottom,
    height,
    slices,
    color.to_bytes(),
  )
}

///|
pub fn draw_cylinder_wires(
  position : Vector3,
  radius_top : Float,
  radius_bottom : Float,
  height : Float,
  slices : Int,
  color : Color,
) -> Unit {
  @ffi.draw_cylinder_wires(
    position.to_bytes(),
    radius_top,
    radius_bottom,
    height,
    slices,
    color.to_bytes(),
  )
}

///|
pub fn draw_triangle_3d(
  v1 : Vector3,
  v2 : Vector3,
  v3 : Vector3,
  color : Color,
) -> Unit {
  @ffi.draw_triangle_3d(
    v1.to_bytes(),
    v2.to_bytes(),
    v3.to_bytes(),
    color.to_bytes(),
  )
}

///|
pub fn draw_cylinder_ex(
  start_pos : Vector3,
  end_pos : Vector3,
  start_radius : Float,
  end_radius : Float,
  sides : Int,
  color : Color,
) -> Unit {
  @ffi.draw_cylinder_ex(
    start_pos.to_bytes(),
    end_pos.to_bytes(),
    start_radius,
    end_radius,
    sides,
    color.to_bytes(),
  )
}

///|
pub fn draw_cylinder_wires_ex(
  start_pos : Vector3,
  end_pos : Vector3,
  start_radius : Float,
  end_radius : Float,
  sides : Int,
  color : Color,
) -> Unit {
  @ffi.draw_cylinder_wires_ex(
    start_pos.to_bytes(),
    end_pos.to_bytes(),
    start_radius,
    end_radius,
    sides,
    color.to_bytes(),
  )
}

///|
pub fn draw_capsule(
  start_pos : Vector3,
  end_pos : Vector3,
  radius : Float,
  slices : Int,
  rings : Int,
  color : Color,
) -> Unit {
  @ffi.draw_capsule(
    start_pos.to_bytes(),
    end_pos.to_bytes(),
    radius,
    slices,
    rings,
    color.to_bytes(),
  )
}

///|
pub fn draw_capsule_wires(
  start_pos : Vector3,
  end_pos : Vector3,
  radius : Float,
  slices : Int,
  rings : Int,
  color : Color,
) -> Unit {
  @ffi.draw_capsule_wires(
    start_pos.to_bytes(),
    end_pos.to_bytes(),
    radius,
    slices,
    rings,
    color.to_bytes(),
  )
}

///|
pub fn draw_plane(center : Vector3, size : Vector2, color : Color) -> Unit {
  @ffi.draw_plane(center.to_bytes(), size.to_bytes(), color.to_bytes())
}

///|
pub fn draw_ray(ray : Ray, color : Color) -> Unit {
  @ffi.draw_ray(ray.to_bytes(), color.to_bytes())
}

///|
pub fn draw_bounding_box(box_ : BoundingBox, color : Color) -> Unit {
  @ffi.draw_bounding_box(box_.to_bytes(), color.to_bytes())
}

// ============================================================================
// Billboard drawing (wrappers)
// ============================================================================

///|
pub fn draw_billboard(
  camera : Camera3D,
  texture : Texture,
  position : Vector3,
  scale : Float,
  tint : Color,
) -> Unit {
  @ffi.draw_billboard(
    camera.to_bytes(),
    texture.0,
    position.to_bytes(),
    scale,
    tint.to_bytes(),
  )
}

///|
pub fn draw_billboard_rec(
  camera : Camera3D,
  texture : Texture,
  source : Rectangle,
  position : Vector3,
  size : Vector2,
  tint : Color,
) -> Unit {
  @ffi.draw_billboard_rec(
    camera.to_bytes(),
    texture.0,
    source.to_bytes(),
    position.to_bytes(),
    size.to_bytes(),
    tint.to_bytes(),
  )
}

///|
pub fn draw_billboard_pro(
  camera : Camera3D,
  texture : Texture,
  source : Rectangle,
  position : Vector3,
  up : Vector3,
  size : Vector2,
  origin : Vector2,
  rotation : Float,
  tint : Color,
) -> Unit {
  @ffi.draw_billboard_pro(
    camera.to_bytes(),
    texture.0,
    source.to_bytes(),
    position.to_bytes(),
    up.to_bytes(),
    size.to_bytes(),
    origin.to_bytes(),
    rotation,
    tint.to_bytes(),
  )
}

// ============================================================================
// 3D collision detection (wrappers)
// ============================================================================

///|
pub fn check_collision_spheres(
  center1 : Vector3,
  radius1 : Float,
  center2 : Vector3,
  radius2 : Float,
) -> Bool {
  @ffi.check_collision_spheres(
    center1.to_bytes(),
    radius1,
    center2.to_bytes(),
    radius2,
  )
}

///|
pub fn check_collision_boxes(box1 : BoundingBox, box2 : BoundingBox) -> Bool {
  @ffi.check_collision_boxes(box1.to_bytes(), box2.to_bytes())
}

///|
pub fn check_collision_box_sphere(
  box_ : BoundingBox,
  center : Vector3,
  radius : Float,
) -> Bool {
  @ffi.check_collision_box_sphere(box_.to_bytes(), center.to_bytes(), radius)
}

///|
pub fn get_ray_collision_sphere(
  ray : Ray,
  center : Vector3,
  radius : Float,
) -> RayCollision {
  RayCollision::from_bytes(
    @ffi.get_ray_collision_sphere(ray.to_bytes(), center.to_bytes(), radius),
  )
}

///|
pub fn get_ray_collision_box(ray : Ray, box_ : BoundingBox) -> RayCollision {
  RayCollision::from_bytes(
    @ffi.get_ray_collision_box(ray.to_bytes(), box_.to_bytes()),
  )
}

///|
pub fn get_ray_collision_triangle(
  ray : Ray,
  p1 : Vector3,
  p2 : Vector3,
  p3 : Vector3,
) -> RayCollision {
  RayCollision::from_bytes(
    @ffi.get_ray_collision_triangle(
      ray.to_bytes(),
      p1.to_bytes(),
      p2.to_bytes(),
      p3.to_bytes(),
    ),
  )
}

///|
pub fn get_ray_collision_mesh(
  ray : Ray,
  mesh : Mesh,
  transform : Matrix,
) -> RayCollision {
  RayCollision::from_bytes(
    @ffi.get_ray_collision_mesh(ray.to_bytes(), mesh.0, transform.to_bytes()),
  )
}

///|
pub fn get_ray_collision_quad(
  ray : Ray,
  p1 : Vector3,
  p2 : Vector3,
  p3 : Vector3,
  p4 : Vector3,
) -> RayCollision {
  RayCollision::from_bytes(
    @ffi.get_ray_collision_quad(
      ray.to_bytes(),
      p1.to_bytes(),
      p2.to_bytes(),
      p3.to_bytes(),
      p4.to_bytes(),
    ),
  )
}

// ============================================================================
// Material map type constants
// ============================================================================

///|
pub const MaterialMapAlbedo : Int = 0

///|
pub const MaterialMapMetalness : Int = 1

///|
pub const MaterialMapNormal : Int = 2

///|
pub const MaterialMapRoughness : Int = 3

///|
pub const MaterialMapOcclusion : Int = 4

///|
pub const MaterialMapEmission : Int = 5

///|
pub const MaterialMapHeight : Int = 6

///|
pub const MaterialMapCubemap : Int = 7

///|
pub const MaterialMapIrradiance : Int = 8

///|
pub const MaterialMapPrefilter : Int = 9

///|
pub const MaterialMapBrdf : Int = 10