#!/usr/bin/env bash

set -e
set -o nounset
set -o pipefail

THIS_FILE=${BASH_SOURCE[0]}
LOG_LABEL=$(basename "$THIS_FILE")
# Allows script name to be set when called from a parent script or defaults to filename.
THIS=${THIS:-$LOG_LABEL}
LOG_FILE=${LOG_FILE:-$LOG_LABEL.log}

usage() {
  cat <<EOF

Close window(s) by address or pattern mode.

USAGE:
  $ $THIS [OPTIONS] [MODE] [ARG...]

MODE:
  --all:                      Close all windows in all workspaces, any arguments are ignored.

  -a | --active-workspace:    Close all windows in the active workspace, any arguments are ignored.

  -c | --class:               Close all windows whose class contains one of the passed arguments.

  -s | --special:             Close all windows in special workspaces whose name matches on of the
                              passed in arguments, or if no arguments are supplied then it will close
                              all windows in all special workspaces.
OPTIONS:
--dry-run
-h | --help:      Show this help page.

NOTES:

If a mode is selected all arguments are treated for that mode, meaning only one mode
runs. It does not work to mix modes / arguments.

If no modes are supplied then arguments are assumed to be window addresses and we will
close all supplied window addresses.


EOF
}

active_workspace_flag="0"
all_flag="0"
class_flag="0"
dry_run_flag="0"
special_flag="0"
args=()
addresses=()
SCRIPTS="${SCRIPTS:-$HOME/.local/scripts}"

while [[ $# -gt 0 ]]; do
  if [[ $1 =~ ^-a ]] || [[ $1 =~ ^--active-workspace ]]; then
    active_workspace_flag="1"
  elif [[ $1 =~ ^--all ]]; then
    all_flag="1"
  elif [[ $1 =~ ^-c ]] || [[ $1 =~ ^--class ]]; then
    class_flag="1"
  elif [[ $1 =~ ^--dry-run ]]; then
    dry_run_flag="1"
  elif [[ $1 =~ ^-h ]] || [[ $1 =~ ^--help ]]; then
    usage && exit 0
  elif [[ $1 =~ ^-s ]] || [[ $1 =~ ^--special ]]; then
    special_flag="1"
  else
    args+=($1)
  fi
  shift
done

log() {
  logging log --source "$THIS_FILE" "$@"
}

_select_addresses() {
  local property=$1
  local pattern=$2
  addresses+=("$(hyprctl clients -j | jq -r ".[] | select($property | contains(\"$pattern\")) | .address")")
}

get_special_addresses() {

  # If no arguments, then we add the "special" to the pattern args, which will
  # match all windows in any special workspace.
  if [[ ${#args} == 0 ]]; then
    args+=("special")
  fi

  for name in ${args[@]}; do
    log "Fetching addresses for special: $name"
    _select_addresses .workspace.name $name
  done
}

close() {
  log "Closing window address: $1"
  if [[ $dry_run_flag == "0" ]]; then
    hyprctl dispatch closewindow "address:$1" >/dev/null 2>&1
  fi
}

################################################################################
# MAIN
################################################################################

# Setup logging file and label
source "$SCRIPTS/hypr/logging"
setup-logging "$LOG_FILE" "$LOG_LABEL"
export LOG_ENABLE_DRY_RUN="$dry_run_flag"

if [[ $active_workspace_flag == "1" ]]; then
  # Set addresses to active workspace windows.
  id=$(hyprctl activeworkspace -j | jq -r '.id')
  log "Fetching addresses for active workspace: $id"
  addresses+=("$(hyprctl clients -j | jq -r ".[] | select(.workspace.id == $id) | .address")")

elif [[ $all_flag == "1" ]]; then
  # Set addresses to all window addresses.
  addresses+=("$(hyprctl clients -j | jq -r ".[] | .address")")

elif [[ $class_flag == "1" ]]; then
  # Set addresses to all windows containing the passed in classes.
  for c in ${args[@]}; do
    _select_addresses .class $c
  done

elif [[ $special_flag == "1" ]]; then
  # Set addresses to all windows in the passed in special workspaces.
  get_special_addresses

else
  # If no modes selected, then assume there were addresses passed in
  # as args.
  addresses=("$args")
fi

if [[ ${#addresses} == 0 ]]; then
  log --warning "No windows found."
  exit 0
fi

for address in ${addresses[@]}; do
  close $address
done
