// GLFW バインディング(ウィンドウ管理用)

///|
// 不透明ポインタ型
#external
type GLFWwindow

///|
// ===============================
// 構造体定義
// ===============================

///|
pub(all) struct WindowSize {
  width : Int
  height : Int
}

///|
// ===============================
// C関数の宣言(extern "C")
// ===============================

// GLFW 初期化
extern "C" fn glfwInit() -> Int = "glfwInit"

///|
extern "C" fn glfwTerminate() -> Unit = "glfwTerminate"

///|
// ウィンドウ作成(安全なラッパー経由)
#borrow(title)
extern "C" fn moonbit_glfw_create_window_safe(
  width : Int,
  height : Int,
  title : String,
) -> GLFWwindow = "moonbit_glfw_create_window_safe"

///|
extern "C" fn glfwDestroyWindow(window : GLFWwindow) -> Unit = "glfwDestroyWindow"

// イベント処理

///|
extern "C" fn glfwPollEvents() -> Unit = "glfwPollEvents"

///|
extern "C" fn glfwWindowShouldClose(window : GLFWwindow) -> Int = "glfwWindowShouldClose"

///|
extern "C" fn glfwSetWindowShouldClose(
  window : GLFWwindow,
  value : Int,
) -> Unit = "glfwSetWindowShouldClose"

///|
// SwapBuffers(バックバッファとフロントバッファを交換)
extern "C" fn glfwSwapBuffers(window : GLFWwindow) -> Unit = "glfwSwapBuffers"

///|
extern "C" fn glfwSwapInterval(interval : Int) -> Unit = "glfwSwapInterval"

///|
// ウィンドウサイズ取得(分割版)
extern "C" fn glfwGetWindowWidth(window : GLFWwindow) -> Int = "moonbit_glfw_get_window_width"

///|
extern "C" fn glfwGetWindowHeight(window : GLFWwindow) -> Int = "moonbit_glfw_get_window_height"

///|
// フレームバッファサイズ取得(物理ピクセル、Retina対応)
extern "C" fn glfwGetFramebufferWidth(window : GLFWwindow) -> Int = "moonbit_glfw_get_framebuffer_width"

///|
extern "C" fn glfwGetFramebufferHeight(window : GLFWwindow) -> Int = "moonbit_glfw_get_framebuffer_height"

///|
extern "C" fn moonbit_glfw_set_fullscreen(
  window : GLFWwindow,
  enabled : Int,
) -> Int = "moonbit_glfw_set_fullscreen"

///|
extern "C" fn moonbit_glfw_is_fullscreen(window : GLFWwindow) -> Int = "moonbit_glfw_is_fullscreen"

///|
extern "C" fn moonbit_glfw_set_cursor_mode(
  window : GLFWwindow,
  mode : Int,
) -> Int = "moonbit_glfw_set_cursor_mode"

///|
extern "C" fn moonbit_glfw_get_cursor_mode(window : GLFWwindow) -> Int = "moonbit_glfw_get_cursor_mode"

///|
extern "C" fn moonbit_glfw_get_cursor_x(window : GLFWwindow) -> Double = "moonbit_glfw_get_cursor_x"

///|
extern "C" fn moonbit_glfw_get_cursor_y(window : GLFWwindow) -> Double = "moonbit_glfw_get_cursor_y"

///|
extern "C" fn moonbit_glfw_take_scroll_x(window : GLFWwindow) -> Double = "moonbit_glfw_take_scroll_x"

///|
extern "C" fn moonbit_glfw_take_scroll_y(window : GLFWwindow) -> Double = "moonbit_glfw_take_scroll_y"

///|
extern "C" fn moonbit_glfw_pressed_key_count(window : GLFWwindow) -> Int = "moonbit_glfw_pressed_key_count"

///|
extern "C" fn moonbit_glfw_pressed_key_at(
  window : GLFWwindow,
  index : Int,
) -> Int = "moonbit_glfw_pressed_key_at"

///|
extern "C" fn moonbit_glfw_pressed_mouse_button_count(
  window : GLFWwindow,
) -> Int = "moonbit_glfw_pressed_mouse_button_count"

///|
extern "C" fn moonbit_glfw_pressed_mouse_button_at(
  window : GLFWwindow,
  index : Int,
) -> Int = "moonbit_glfw_pressed_mouse_button_at"

///|
extern "C" fn moonbit_glfw_touch_count(window : GLFWwindow) -> Int = "moonbit_glfw_touch_count"

///|
extern "C" fn moonbit_glfw_touch_id_at(window : GLFWwindow, index : Int) -> Int = "moonbit_glfw_touch_id_at"

///|
extern "C" fn moonbit_glfw_touch_x_at(
  window : GLFWwindow,
  index : Int,
) -> Double = "moonbit_glfw_touch_x_at"

///|
extern "C" fn moonbit_glfw_touch_y_at(
  window : GLFWwindow,
  index : Int,
) -> Double = "moonbit_glfw_touch_y_at"

///|
extern "C" fn moonbit_glfw_touch_type_at(
  window : GLFWwindow,
  index : Int,
) -> Int = "moonbit_glfw_touch_type_at"

///|
extern "C" fn moonbit_glfw_gamepad_count() -> Int = "moonbit_glfw_gamepad_count"

///|
extern "C" fn moonbit_glfw_gamepad_id_at(index : Int) -> Int = "moonbit_glfw_gamepad_id_at"

///|
extern "C" fn moonbit_glfw_gamepad_axis_count(index : Int) -> Int = "moonbit_glfw_gamepad_axis_count"

///|
extern "C" fn moonbit_glfw_gamepad_axis_at(
  gamepad_index : Int,
  axis_index : Int,
) -> Double = "moonbit_glfw_gamepad_axis_at"

///|
extern "C" fn moonbit_glfw_gamepad_pressed_button_count(index : Int) -> Int = "moonbit_glfw_gamepad_pressed_button_count"

///|
extern "C" fn moonbit_glfw_gamepad_pressed_button_at(
  gamepad_index : Int,
  button_index : Int,
) -> Int = "moonbit_glfw_gamepad_pressed_button_at"

///|
extern "C" fn moonbit_glfw_get_window_content_scale(
  window : GLFWwindow,
) -> Double = "moonbit_glfw_get_window_content_scale"

///|
extern "C" fn moonbit_glfw_request_window_attention_safe(
  window : GLFWwindow,
) -> Unit = "moonbit_glfw_request_window_attention_safe"

///|
// ===============================
// 高レベルラッパー関数
// ===============================

// GLFW 初期化
pub fn glfw_init() -> Bool {
  glfwInit() != 0
}

///|
pub fn terminate() -> Unit {
  glfwTerminate()
}

///|
// ウィンドウ作成(WebGPU 用に CLIENT_API を NO_API に設定)
pub fn create_window(width : Int, height : Int, title : String) -> GLFWwindow {
  // C スタブの安全なラッパー経由でウィンドウ作成
  // (ウィンドウヒント設定も含む)
  moonbit_glfw_create_window_safe(width, height, title)
}

///|
extern "C" fn moonbit_glfw_create_hidden_window(
  width : Int,
  height : Int,
) -> GLFWwindow = "moonbit_glfw_create_hidden_window"

///|
/// Create a hidden (invisible) GLFW window for headless rendering.
pub fn create_hidden_window(width : Int, height : Int) -> GLFWwindow {
  moonbit_glfw_create_hidden_window(width, height)
}

///|
pub fn destroy_window(window : GLFWwindow) -> Unit {
  glfwDestroyWindow(window)
}

///|
pub fn poll_events() -> Unit {
  glfwPollEvents()
}

///|
pub fn window_should_close(window : GLFWwindow) -> Bool {
  glfwWindowShouldClose(window) != 0
}

///|
pub fn set_window_should_close(window : GLFWwindow, value : Bool) -> Unit {
  glfwSetWindowShouldClose(window, if value { 1 } else { 0 })
}

///|
pub fn swap_buffers(window : GLFWwindow) -> Unit {
  glfwSwapBuffers(window)
}

///|
pub fn set_swap_interval(enabled : Bool) -> Unit {
  glfwSwapInterval(if enabled { 1 } else { 0 })
}

///|
pub fn get_window_size(window : GLFWwindow) -> WindowSize {
  // moonbit_glfw_get_window_size_struct(window)  // 構造体返却版(クラッシュ)
  // 代わりに分割版を使用
  { width: glfwGetWindowWidth(window), height: glfwGetWindowHeight(window) }
}

///|
pub fn get_window_width(window : GLFWwindow) -> Int {
  glfwGetWindowWidth(window)
}

///|
pub fn get_window_height(window : GLFWwindow) -> Int {
  glfwGetWindowHeight(window)
}

///|
pub fn get_framebuffer_size(window : GLFWwindow) -> WindowSize {
  {
    width: glfwGetFramebufferWidth(window),
    height: glfwGetFramebufferHeight(window),
  }
}

///|
pub fn set_fullscreen(window : GLFWwindow, enabled : Bool) -> Bool {
  moonbit_glfw_set_fullscreen(window, if enabled { 1 } else { 0 }) != 0
}

///|
pub fn is_fullscreen(window : GLFWwindow) -> Bool {
  moonbit_glfw_is_fullscreen(window) != 0
}

///|
pub fn set_cursor_mode(window : GLFWwindow, mode : Int) -> Int {
  moonbit_glfw_set_cursor_mode(window, mode)
}

///|
pub fn get_cursor_mode(window : GLFWwindow) -> Int {
  moonbit_glfw_get_cursor_mode(window)
}

///|
pub fn get_cursor_x(window : GLFWwindow) -> Double {
  moonbit_glfw_get_cursor_x(window)
}

///|
pub fn get_cursor_y(window : GLFWwindow) -> Double {
  moonbit_glfw_get_cursor_y(window)
}

///|
pub fn take_scroll_x(window : GLFWwindow) -> Double {
  moonbit_glfw_take_scroll_x(window)
}

///|
pub fn take_scroll_y(window : GLFWwindow) -> Double {
  moonbit_glfw_take_scroll_y(window)
}

///|
pub fn pressed_key_count(window : GLFWwindow) -> Int {
  moonbit_glfw_pressed_key_count(window)
}

///|
pub fn pressed_key_at(window : GLFWwindow, index : Int) -> Int {
  moonbit_glfw_pressed_key_at(window, index)
}

///|
pub fn pressed_mouse_button_count(window : GLFWwindow) -> Int {
  moonbit_glfw_pressed_mouse_button_count(window)
}

///|
pub fn pressed_mouse_button_at(window : GLFWwindow, index : Int) -> Int {
  moonbit_glfw_pressed_mouse_button_at(window, index)
}

///|
pub fn touch_count(window : GLFWwindow) -> Int {
  moonbit_glfw_touch_count(window)
}

///|
pub fn touch_id_at(window : GLFWwindow, index : Int) -> Int {
  moonbit_glfw_touch_id_at(window, index)
}

///|
pub fn touch_x_at(window : GLFWwindow, index : Int) -> Double {
  moonbit_glfw_touch_x_at(window, index)
}

///|
pub fn touch_y_at(window : GLFWwindow, index : Int) -> Double {
  moonbit_glfw_touch_y_at(window, index)
}

///|
pub fn touch_type_at(window : GLFWwindow, index : Int) -> Int {
  moonbit_glfw_touch_type_at(window, index)
}

///|
pub fn gamepad_count() -> Int {
  moonbit_glfw_gamepad_count()
}

///|
pub fn gamepad_id_at(index : Int) -> Int {
  moonbit_glfw_gamepad_id_at(index)
}

///|
pub fn gamepad_axis_count(index : Int) -> Int {
  moonbit_glfw_gamepad_axis_count(index)
}

///|
pub fn gamepad_axis_at(gamepad_index : Int, axis_index : Int) -> Double {
  moonbit_glfw_gamepad_axis_at(gamepad_index, axis_index)
}

///|
pub fn gamepad_pressed_button_count(index : Int) -> Int {
  moonbit_glfw_gamepad_pressed_button_count(index)
}

///|
pub fn gamepad_pressed_button_at(
  gamepad_index : Int,
  button_index : Int,
) -> Int {
  moonbit_glfw_gamepad_pressed_button_at(gamepad_index, button_index)
}

///|
pub fn get_window_content_scale(window : GLFWwindow) -> Double {
  let scale = moonbit_glfw_get_window_content_scale(window)
  if scale <= 0.0 {
    1.0
  } else {
    scale
  }
}

///|
pub fn request_window_attention(window : GLFWwindow) -> Unit {
  moonbit_glfw_request_window_attention_safe(window)
}