#!/bin/bash
# Usage: mirrordash-gpio-overlays [type:value ...]
#   button, button_2..4, pir, mmwave, dht11: GPIO number 2-27      light (BH1750 on I2C): 0x23 or 0x5c
#   fan, pwm_fan: GPIO:temperature, e.g. fan:14:60 (switch-on temperature 40-80 °C)
# Each type at most once, one fan, every GPIO at most once, GPIO 2/3 reserved while I2C is used.
set -euo pipefail

die() { echo "$*" >&2; exit 2; }
declare -A seen_type=() seen_pin=()
lines=()
for arg in "$@"; do
  type=${arg%%:*} value=${arg#*:} temp=""
  if [ "$type" = fan ] || [ "$type" = pwm_fan ]; then
    temp=${value#*:} value=${value%%:*}
    { [[ "$temp" =~ ^[0-9]+$ ]] && [ "$temp" -ge 40 ] && [ "$temp" -le 80 ]; } || die "invalid fan temperature: $arg"
  fi
  [ -z "${seen_type[$type]:-}" ] || die "$type given twice"
  seen_type[$type]=1
  case "$type" in
    button|button_2|button_3|button_4|pir|mmwave|dht11|fan|pwm_fan)
      { [[ "$value" =~ ^[0-9]+$ ]] && [ "$value" -ge 2 ] && [ "$value" -le 27 ]; } || die "invalid GPIO: $arg"
      [ -z "${seen_pin[$value]:-}" ] || die "GPIO $value used twice"
      seen_pin[$value]=1 ;;
    light)
      [ "$value" = 0x23 ] || [ "$value" = 0x5c ] || die "invalid I2C address: $arg" ;;
    *)
      die "unknown device type: $arg" ;;
  esac
  case "$type" in
    # Buttons/sensors become input devices (keycodes KEY_PROG1-3, KEY_MACRO1-3): kernel debounce, no polling
    button) lines+=("dtoverlay=gpio-key,gpio=$value,active_low=1,gpio_pull=up,keycode=148,label=mirrordash-button") ;;
    button_2) lines+=("dtoverlay=gpio-key,gpio=$value,active_low=1,gpio_pull=up,keycode=656,label=mirrordash-button-2") ;;
    button_3) lines+=("dtoverlay=gpio-key,gpio=$value,active_low=1,gpio_pull=up,keycode=657,label=mirrordash-button-3") ;;
    button_4) lines+=("dtoverlay=gpio-key,gpio=$value,active_low=1,gpio_pull=up,keycode=658,label=mirrordash-button-4") ;;
    pir)    lines+=("dtoverlay=gpio-key,gpio=$value,active_low=0,gpio_pull=down,keycode=149,label=mirrordash-pir") ;;
    mmwave) lines+=("dtoverlay=gpio-key,gpio=$value,active_low=0,gpio_pull=down,keycode=150,label=mirrordash-mmwave") ;;
    dht11)  lines+=("dtoverlay=dht11,gpiopin=$value") ;;
    light)  lines+=("dtparam=i2c_arm=on" "dtoverlay=i2c-sensor,bh1750,addr=$value") ;;
    # The kernel's thermal framework runs the fan by CPU temperature (millidegrees)
    fan)    lines+=("dtoverlay=gpio-fan,gpiopin=$value,temp=$((temp * 1000)),hyst=5000") ;;
    pwm_fan) lines+=("dtoverlay=pwm-gpio-fan,fan_gpio=$value,fan_temp0=$((temp * 1000)),fan_temp1=$((temp * 1000 + 5000)),fan_temp2=$((temp * 1000 + 12500)),fan_temp3=$((temp * 1000 + 20000))") ;;
  esac
done
if [ -n "${seen_type[fan]:-}" ] && [ -n "${seen_type[pwm_fan]:-}" ]; then die "only one fan"; fi
if [ -n "${seen_type[light]:-}" ] && { [ -n "${seen_pin[2]:-}" ] || [ -n "${seen_pin[3]:-}" ]; }; then
  die "GPIO 2 and 3 are needed for I2C"
fi

CONFIG=/boot/firmware/config.txt
BEGIN='# --- MirrorDash GPIO (managed by the admin page) ---'
END='# --- end MirrorDash GPIO ---'

{
  awk -v b="$BEGIN" -v e="$END" '$0 == b { skip = 1 } !skip { print } $0 == e { skip = 0 }' "$CONFIG"
  echo "$BEGIN"
  echo "[all]"  # applies to every Pi model, whatever section the file ended in
  if [ ${#lines[@]} -gt 0 ]; then printf '%s\n' "${lines[@]}"; fi
  echo "$END"
} > "$CONFIG.mirrordash-tmp"
mv "$CONFIG.mirrordash-tmp" "$CONFIG"
sync
