#!/bin/bash

USAGE="
USAGE: avds <mod_list|-h|-[-]help> [<when>] [<repeat>]

        mod_list
                A comma or space separated list of modules to request that
                the daemon execute.

        when    The integer number of milliseconds to wait before sending the
                request, or one of the following values:
                  - m to send the update request at the top of the next minute
                  - h to send the update request at the top of the next hour
                  - d to send the update request at the top of the next day
                If not present, the request will be sent immediately.

        repeat  If present, the request will be sent repeatedly according
                to <when>.

EXAMPLES:

        Any of these will display this help message.

                avds -h
                avds -help
                avds --help

        If there are volume and backlight modules named 'vol' and 'bl' that
        update the volume and backlight statuses, send a requst to update
        both of those statuses immediately.

                avds 'vol,bl'

        If there are cpu and memory usage modules named 'cpu' and 'mem'
        that update the cpu and memory usage statuses, send a requst to
        update both of those statuses every 5 seconds.

                avds 'cpu,mem' 5000 1

        If there are battery and date/time modules named 'bat' and 'dt'
        that update the battery and date/time statuses, send a requst to
        update both of those statuses at the top of every minute.

                avds 'bat,dt' m true
"
DAEMON=avdd
FIFO=/tmp/"${DAEMON}"-fifo-"$("$(dirname "$0")"/rpid)"

# Convert integer milliseconds to floating point seconds
ms_to_s() {
  printf '%.3f' "${1}e-3"
}

# Validate the number arguments
if [[ "$#" -lt 1 || "$#" -gt 3 ]]; then
  printf '%s' "${USAGE}" 1>&2
  exit 128
fi

mod_list="$1"

# Check if the user needs help
if [[ "${mod_list}" =~ ^(-h|-(-)?help)$ ]]; then
  printf '%s' "${USAGE}" 1>&2
  exit 0
fi

when="${2:-0}"

# Validate when
if [[ ! "${when}" =~ ^[0-9]+|[mhd]$ ]]; then
  printf 'Invalid argument <when>: %s\n' "${when}" 1>&2
  exit 128
fi

repeat="$3"

# Write to the pipe if this is the first run or if repeat is on
first_run=1
while [[ "${first_run}" -eq 1 || -n "${repeat}" ]]; do
  first_run=0

  # Sleep until it's time to write to the pipe
  if [[ "${when}" != '0' ]]; then
    if [[ "${when}" =~ ^[0-9]+$ ]]; then
      sleep "$(ms_to_s "${when}")"
    else
      case "${when}" in
        m)
          sleep $((60 - $(date +%S)))
          ;;
        h)
          readarray -t ms < <(date +'%M%n%S')
          sleep $((3600 - ms[0] * 60 - ms[1]))
          ;;
        d)
          readarray -t hms < <(date +'%H%n%M%n%S')
          sleep $(((24 - hms[0]) * 3600 - hms[1] * 60 - hms[2]))
          ;;
        *)
          ;;
      esac
    fi
  fi

  # Write each command to the pipe
  if [[ ! -p "${FIFO}" ]]; then
    printf 'The daemon %s is not running\n' "${DAEMON}" 1>&2
    exit 1
  fi
  printf '%s\n' "${mod_list}" >> "${FIFO}"
done