///|
/// Input event types for CDP Input domain
/// Based on Chrome DevTools Protocol specification

///|
/// Mouse button type
pub(all) enum MouseButton {
  None
  Left
  Middle
  Right
  Back
  Forward
} derive(Eq, Debug)

///|
/// Mouse event type
pub(all) enum MouseEventType {
  MousePressed
  MouseReleased
  MouseMoved
  MouseWheel
} derive(Eq, Debug)

///|
/// Keyboard event type
pub(all) enum KeyEventType {
  KeyDown
  KeyUp
  RawKeyDown
  Char
} derive(Eq, Debug)

///|
/// Mouse event data
pub(all) struct MouseEvent {
  event_type : MouseEventType
  x : Double
  y : Double
  button : MouseButton
  buttons : Int // Bitmask of pressed buttons
  click_count : Int
  modifiers : Int // Alt=1, Ctrl=2, Meta=4, Shift=8
  timestamp : Double
} derive(Debug)

///|
pub fn MouseEvent::new(
  event_type : MouseEventType,
  x : Double,
  y : Double,
) -> MouseEvent {
  {
    event_type,
    x,
    y,
    button: MouseButton::None,
    buttons: 0,
    click_count: 1,
    modifiers: 0,
    timestamp: 0.0,
  }
}

///|
pub fn MouseEvent::with_button(
  self : MouseEvent,
  button : MouseButton,
) -> MouseEvent {
  { ..self, button, }
}

///|
pub fn MouseEvent::with_modifiers(
  self : MouseEvent,
  modifiers : Int,
) -> MouseEvent {
  { ..self, modifiers, }
}

///|
/// Keyboard event data
pub(all) struct KeyboardEvent {
  event_type : KeyEventType
  key : String // Key value (e.g., "Enter", "a")
  code : String // Physical key code (e.g., "Enter", "KeyA")
  modifiers : Int // Alt=1, Ctrl=2, Meta=4, Shift=8
  text : String? // Text generated by the key
  timestamp : Double
} derive(Debug)

///|
pub fn KeyboardEvent::new(
  event_type : KeyEventType,
  key : String,
) -> KeyboardEvent {
  { event_type, key, code: "", modifiers: 0, text: None, timestamp: 0.0 }
}

///|
pub fn KeyboardEvent::with_code(
  self : KeyboardEvent,
  code : String,
) -> KeyboardEvent {
  { ..self, code, }
}

///|
pub fn KeyboardEvent::with_modifiers(
  self : KeyboardEvent,
  modifiers : Int,
) -> KeyboardEvent {
  { ..self, modifiers, }
}

///|
pub fn KeyboardEvent::with_text(
  self : KeyboardEvent,
  text : String,
) -> KeyboardEvent {
  { ..self, text: Some(text) }
}

///|
/// Check if Alt modifier is set
pub fn has_alt(modifiers : Int) -> Bool {
  (modifiers & 1) != 0
}

///|
/// Check if Ctrl modifier is set
pub fn has_ctrl(modifiers : Int) -> Bool {
  (modifiers & 2) != 0
}

///|
/// Check if Meta modifier is set
pub fn has_meta(modifiers : Int) -> Bool {
  (modifiers & 4) != 0
}

///|
/// Check if Shift modifier is set
pub fn has_shift(modifiers : Int) -> Bool {
  (modifiers & 8) != 0
}

///|
/// Input event (mouse or keyboard)
pub(all) enum InputEvent {
  Mouse(MouseEvent)
  Keyboard(KeyboardEvent)
  Text(String) // insertText
} derive(Debug)

///|
pub impl Show for MouseButton with fn output(self, logger) {
  let name = match self {
    None => "None"
    Left => "Left"
    Middle => "Middle"
    Right => "Right"
    Back => "Back"
    Forward => "Forward"
  }
  logger.write_string(name)
}

///|
pub impl Show for MouseEventType with fn output(self, logger) {
  let name = match self {
    MousePressed => "MousePressed"
    MouseReleased => "MouseReleased"
    MouseMoved => "MouseMoved"
    MouseWheel => "MouseWheel"
  }
  logger.write_string(name)
}

///|
pub impl Show for KeyEventType with fn output(self, logger) {
  let name = match self {
    KeyDown => "KeyDown"
    KeyUp => "KeyUp"
    RawKeyDown => "RawKeyDown"
    Char => "Char"
  }
  logger.write_string(name)
}

///|
pub impl Show for MouseEvent with fn output(self, logger) {
  logger.write_string(
    "{event_type: \{self.event_type}, x: \{self.x}, y: \{self.y}, ",
  )
  logger.write_string("button: \{self.button}, buttons: \{self.buttons}, ")
  logger.write_string(
    "click_count: \{self.click_count}, modifiers: \{self.modifiers}, ",
  )
  logger.write_string("timestamp: \{self.timestamp}}")
}

///|
pub impl Show for KeyboardEvent with fn output(self, logger) {
  logger.write_string("{event_type: \{self.event_type}, key: ")
  logger.write_string("\"")
  logger.write_string(self.key)
  logger.write_string("\"")
  logger.write_string(", code: ")
  logger.write_string("\"")
  logger.write_string(self.code)
  logger.write_string("\"")
  logger.write_string(", modifiers: ")
  logger.write_object(to_repr(self.modifiers))
  logger.write_string(", text: ")
  logger.write_object(to_repr(self.text))
  logger.write_string(", ")
  logger.write_string("timestamp: \{self.timestamp}}")
}

///|
pub impl Show for InputEvent with fn output(self, logger) {
  match self {
    Mouse(event) => logger.write_string("Mouse(\{event})")
    Keyboard(event) => logger.write_string("Keyboard(\{event})")
    Text(text) => {
      logger.write_string("Text(")
      logger.write_string("\"")
      logger.write_string(text)
      logger.write_string("\"")
      logger.write_string(")")
    }
  }
}

///|
/// Input manager for handling input events
pub struct InputManager {
  pending_events : Array[InputEvent]
  mut enabled : Bool
}

///|
pub fn InputManager::new() -> InputManager {
  { pending_events: [], enabled: false }
}

///|
pub fn InputManager::enable(self : InputManager) -> Unit {
  self.enabled = true
}

///|
pub fn InputManager::disable(self : InputManager) -> Unit {
  self.enabled = false
}

///|
pub fn InputManager::queue_event(
  self : InputManager,
  event : InputEvent,
) -> Unit {
  if self.enabled {
    self.pending_events.push(event)
  }
}

///|
pub fn InputManager::take_events(self : InputManager) -> Array[InputEvent] {
  let events = self.pending_events.copy()
  self.pending_events.clear()
  events
}