#!/usr/bin/env bash

OUTPUT_COUNT=0

# Fast-path: if called as 'identify' return 60 immediately (used by sensor-control)
if [[ "$1" == "identify" ]]; then
  exit 60
fi

# Collect sensor folders (preserve order)
mapfile -t _folders < <(for f in /sys/bus/w1/devices/28-*/; do [ -d "$f" ] && printf '%s\n' "$f"; done)

if [ "${#_folders[@]}" -eq 0 ]; then
  echo "[]"
  echo "Warning: No DS18B20 sensors detected. Please check your wiring and ensure 1-Wire is enabled." >&2
  exit 0
fi

# initialize PID array for background workers
pids=()

# Concurrency: number of parallel workers (use nproc if available)
PARALLEL=${PARALLEL:-$(nproc --all 2>/dev/null || echo 4)}
# Don't create more workers than sensors
if [ "$PARALLEL" -gt "${#_folders[@]}" ]; then
  PARALLEL=${#_folders[@]}
fi

# Precompute JSON template from sc-prototype (faster than calling it per sensor)
if command -v sc-prototype >/dev/null 2>&1; then
  JSON_TEMPLATE=$(sc-prototype)
  USE_TEMPLATE=1
else
  JSON_TEMPLATE='{}'
  USE_TEMPLATE=0
fi

# Whether the shell supports wait -n (bash 4.3+)
if help wait 2>/dev/null | grep -q -- '-n'; then
  HAVE_WAIT_N=1
else
  HAVE_WAIT_N=0
fi

tempdir=$(mktemp -d -t sensor-ds18b20.XXXX) || { echo "Failed to create temp dir" >&2; exit 1; }
# ensure tempdir is removed on exit
trap 'rm -rf "$tempdir"' EXIT

# Launch workers
i=0
for folder in "${_folders[@]}"; do
  idx=$i
  (
    # Extract sensor ID (pure bash)
    SENSOR_ID="${folder%/}"
    SENSOR_ID="${SENSOR_ID##*/}"

    # Read temperature value from w1_slave file
    if [[ -f "$folder/w1_slave" ]]; then
      temp_raw=$(awk -F'=' '/t=/ {print $2}' "$folder/w1_slave")
      # Use awk for floating point division
      TEMP=$(awk "BEGIN {printf \"%.3f\", $temp_raw/1000}")
      if [[ -z "$TEMP" || ! "$TEMP" =~ ^-?[0-9]+(\.[0-9]+)?$ ]]; then
        printf '%s\n' "__ERROR__" > "$tempdir/$idx.err"
        exit 0
      fi
    else
      printf '%s\n' "__ERROR__" > "$tempdir/$idx.err"
      exit 0
    fi

    if [ "${USE_TEMPLATE:-0}" -eq 1 ]; then
      JSON="$JSON_TEMPLATE"
    else
      JSON=$(sc-prototype)
    fi
    SENSOR=$(printf '%s\n' "$JSON" | jq ".sensor |= \"ds18b20\" | .measures |= \"temperature\" | .unit |= \"Celsius\" | .value |= ${TEMP} | .sensor_id |= \"${SENSOR_ID}\"")
    printf '%s\n' "$SENSOR" > "$tempdir/$idx.json"
  ) &
  pid=$!
  pids+=($pid)
  # Throttle workers: prefer wait -n for low-overhead notification if available
  if [ "${HAVE_WAIT_N:-0}" -eq 1 ]; then
    # wait -n returns when any child exits; loop until we have capacity
    while [ "$(jobs -p | wc -l)" -ge "$PARALLEL" ]; do
      wait -n || true
    done
  else
    # Fallback: maintain PID array and poll
    while [ "${#pids[@]}" -ge "$PARALLEL" ]; do
      newpids=()
      for p in "${pids[@]}"; do
        if kill -0 "$p" 2>/dev/null; then
          newpids+=("$p")
        fi
      done
      pids=("${newpids[@]}")
      if [ "${#pids[@]}" -ge "$PARALLEL" ]; then
        sleep 0.05
      fi
    done
  fi

  i=$((i+1))
done

# Wait for remaining background jobs
for p in "${pids[@]}"; do
  wait "$p" || true
done

# Assemble JSON array in original order
echo -n "["
first=1
for ((j=0;j<i;j++)); do
  if [ -f "$tempdir/$j.json" ]; then
    if [ $first -eq 0 ]; then
      echo -n ","
    fi
    cat "$tempdir/$j.json"
    OUTPUT_COUNT=$((OUTPUT_COUNT+1))
    first=0
  else
    # print warning for failed sensors
    if [ -f "$tempdir/$j.err" ]; then
      echo "Warning: Failed to read sensor at ${_folders[$j]}" >&2
    fi
  fi
done
echo "]"

if [[ $OUTPUT_COUNT -eq 0 ]]; then
  echo "Warning: No DS18B20 sensors detected. Please check your wiring and ensure 1-Wire is enabled." >&2
fi

