#!/usr/bin/nu

let launcher_apps = open $"($env.HOME)/.config/switchrun/apps.nuon"

def lookup_window_id [running_apps, app_id] {
  let matches = $running_apps | where app_id == $app_id
  if ($matches | is-empty) {
    "none"
  } else {
    $matches | get id | first | into string
  }
}

def switch_to [target_window_id: string] {
  let focus_cmd = {Action: { FocusWindow: { id: ($target_window_id | into int ) } } }
  $focus_cmd | to json -r | socat STDIO $env.NIRI_SOCKET
}

def launch [target_app_id: string] {
  let app = (
    $launcher_apps |
     where app_id == $target_app_id |
     first
  )
  print $app.exec
  print ...$app.args
  if $app != null { run-external $app.exec ...$app.args} else { print "no exec found" }
}

def main [target_app_id: string] {
  let running_apps = niri msg --json windows | from json
  let matches = $running_apps | where app_id == $target_app_id
  print $matches
  if ($matches | is-empty) {
    launch $target_app_id
  } else {
    let focused_matches = $matches | enumerate | where item.is_focused == true | get index
    if ($focused_matches | is-empty) {
      switch_to (($matches | first | get id) | into string)
    } else {
      # In the event of multiple matches, switch to the one after the focused one - wrapping around
      # That way we will cycle through them
      let target_index = ($focused_matches | first) - 1
      print $target_index
      print ($matches | length)
      let target_window = if ($target_index < 0) { $matches | last } else { ($matches | get $target_index) }
      switch_to ($target_window.id | into string)
    }
  }
}

def "main list" [tag?: string] {
  let running_apps = niri msg --json windows | from json

  # Optionally narrow to apps carrying the requested tag.
  let filtered = (if ($tag | is-empty) {
      $launcher_apps
    } else {
      $launcher_apps | where { |app| ($tag in ($app.tags? | default [])) }
    })

  if ($filtered | is-empty) {
    print $"No applications match tag '($tag)'"
    return
  }

  let apps = $filtered | each { |app| $app | insert window_id { lookup_window_id $running_apps $app.app_id } }
  # if the selected app_id is running then
  # focus it by its window id (first window id for that app id is fine)
  # if it's not running then launch it using the app's desktop entry
  #
  let app_lines = $apps | each { $"($in.name) - [($in.app_id), ($in.window_id)]" }

  let prompt = if ($tag | is-empty) { "Launch/Switch" } else { $"Launch/Switch [($tag)]" }
  let selection = $app_lines | each { echo $in } | str join "|" | rofi -dmenu -i -p $prompt -sep "|"
  let parsed = $selection | parse "{name} - [{app_id}, {window_id}]" | first
  let match = $apps | where app_id == $parsed.app_id | first
  if $parsed.window_id == "none" { launch $match.app_id } else { switch_to $match.window_id }
}
