#!/usr/bin/env bash

myCommand=""
debug=""
PODip="192.168.0.151"
PODport="32000"
PPBAkey=""
PPBAname=""
MQTT_HOST="192.168.0.6"
MQTT_USER="" # optional
MQTT_PASS="" # optional
myDevice="all"

do_help() {
  cat << HELP_EOF
Usage: $0 <command> [OPTIONS]
	command is one of:
		--ip) IP of the PPBA API server
		--port) Port of the PPBA API server
		--init) Starts the Unity driver (must do this first)
		--start) Starts the PPBA driver (do this after --init)
		--mqtt) Send HA MQTT discovery information to broker
		--stats) Send MQTT stats to broker
		--power [on|off] <DEV>) Powers on a device (see DEV, below)
		-d|--debug) Print debug information
		-h|--help) print this help information

	You can put multiple commands on the command line; they will be executed sequentially.
	They are scanned for in the order listed above.
	Thus, you can do "$0 --init --start --mqtt" for a one-liner startup script
	DEV is a device name:
		all | quad | var | dew1 | dew2 | autodew
HELP_EOF
  exit
}


do_debug() {
  [ -n "$debug" ] && echo "DEBUG: $*" >&2
}

do_api() {
  ep="${1#/}"
  method="${2:-GET}"
  notes="${3}"
  url="http://${PODip}:${PODport}/${ep}"
  do_debug  "curl -s -X ${method} \"$url\""
  [ -n "$notes" ] && echo "$notes" >&2
  curl -s -X ${method} "$url"
}

do_getKey() {
  # Get POD PPBA unique key and name
  PPBAkey=$(do_api "/Server/DeviceManager/Connected" | jq -r '.data[] | select (.name =="PPBAdvance") | .uniqueKey')
  PPBAname=$(do_api "/Server/DeviceManager/Device/${PPBAkey}/ProfileName" | jq -r '.data')
  do_debug "PPBAkey=$PPBAkey, PPBAname=$PPBAname"
  if [ -z "$PPBAkey" -o -z "$PPBAname" ]; then
    # The PPBA is not powered on or cannot be found
    do_debug "The PPBA is not powered on or cannot be found"
    exit
  fi
}

do_init() {
  do_getKey
  do_api "/Server/Start" PUT "Starting server..." | jq '.status'
  sleep 2
}

do_start() {
  do_getKey
  do_api "/Driver/PPBAdvance/Start?DriverUniqueKey=${PPBAkey}" OPTIONS "Starting PPBAdvance driver..." | jq '.status'
#  do_api "/Driver/PPBAdvance/Power/Hub/Off?DriverUniqueKey=${PPBAkey}" PUT "Turning off Quad Power..." | jq '.status'
#  do_api "/Driver/PPBAdvance/Power/Variable/Off?DriverUniqueKey=${PPBAkey}" PUT "Turning off Variable Power..." | jq '.status'
#  do_api "/Driver/PPBAdvance/Dew/1/Off?DriverUniqueKey=${PPBAkey}" PUT "Turning off Dew Heater 1..." | jq '.status'
#  do_api "/Driver/PPBAdvance/Dew/2/Off?DriverUniqueKey=${PPBAkey}" PUT "Turning off Dew Heater 2..." | jq '.status'
#  do_api "/Driver/PPBAdvance/Dew/Auto/Off?DriverUniqueKey=${PPBAkey}" POST "Turning off Auto Dew..." | jq '.status'
}

do_poweroff() {
  do_getKey
  case "$myDevice" in
    Quad|quad*|All|all) do_api "/Driver/PPBAdvance/Power/Hub/Off?DriverUniqueKey=${PPBAkey}" PUT "Turning Off Quad Power..." | jq '.status';;&
    Var|var*|All|all) do_api "/Driver/PPBAdvance/Power/Variable/Off?DriverUniqueKey=${PPBAkey}" PUT "Turning Off Variable Power..." | jq '.status';;&
    Dew1|dew1|All|all) do_api "/Driver/PPBAdvance/Dew/1/Off?DriverUniqueKey=${PPBAkey}" PUT "Turning Off Dew Heater 1..." | jq '.status';;&
    Dew2|dew2|All|all) do_api "/Driver/PPBAdvance/Dew/2/Off?DriverUniqueKey=${PPBAkey}" PUT "Turning Off Dew Heater 2..." | jq '.status';;&
    Auto*|auto*|All|all) do_api "/Driver/PPBAdvance/Dew/Auto/Off?DriverUniqueKey=${PPBAkey}" POST "Turning Off Auto Dew..." | jq '.status';;
  esac
}

do_poweron() {
  do_getKey
  case "$myDevice" in
    Quad|quad*|All|all) do_api "/Driver/PPBAdvance/Power/Hub/On?DriverUniqueKey=${PPBAkey}" PUT "Turning on Quad Power..." | jq '.status';;&
    Var*|var*|All|all) do_api "/Driver/PPBAdvance/Power/Variable/On?DriverUniqueKey=${PPBAkey}" PUT "Turning on Variable Power..." | jq '.status';;&
    Dew1|dew1|All|all) do_api "/Driver/PPBAdvance/Dew/1/On?DriverUniqueKey=${PPBAkey}" PUT "Turning on Dew Heater 1..." | jq '.status';;&
    Dew2|dew2|All|all) do_api "/Driver/PPBAdvance/Dew/2/On?DriverUniqueKey=${PPBAkey}" PUT "Turning on Dew Heater 2..." | jq '.status';;&
    Auto*|auto|All|all) do_api "/Driver/PPBAdvance/Dew/Auto/On?DriverUniqueKey=${PPBAkey}" POST "Turning on Auto Dew..." | jq '.status';;
  esac
}


mqtt_pub() {
  topic="$1"
  message="$2"
  do_debug "mosquitto_pub -h $MQTT_HOST -t \"PPBA/status/$topic\" -m \"$message\""
  mosquitto_pub -h $MQTT_HOST -t "PPBA/status/$topic" -m "$message" -r
}

do_stats() {
  do_getKey
  stats=$(do_api "/Driver/PPBAdvance/Report?DriverUniqueKey=${PPBAkey}")
  for stat in "voltage" "current" "quadCurrent" "power" "temperature" "humidity" "dewPoint" "isOverCurrent" "averageAmps" "ampsPerHour" "wattPerHour" "upTime"; do
    val=$(echo "$stats" | jq -r ".data.message.$stat")
    mqtt_pub "$stat" "$val"
  done
  for stat in "powerHubStatus" "powerVariablePortStatus" "ppbA_DualUSB2Status"; do
    val=$(echo "$stats" | jq -r ".data.message.$stat.state")
    mqtt_pub "$stat" "$val"
  done
}

###
###

do_mqtt() {
  do_getKey
  JSON_DATA=$(do_api "/Driver/PPBAdvance/Report?DriverUniqueKey=${PPBAkey}")
  DEVICE_ID="ppbadv_gen2"
  DISCOVERY_PREFIX="homeassistant"
  STATE_TOPIC="$DEVICE_ID/state"
  STATE_TOPIC="PPBA/status"
  POLL_INTERVAL=30     # seconds

  publish_discovery() {
    echo "Publishing Home Assistant MQTT discovery configs..."
    # Helper to publish a single discovery config message
    publish_sensor() {
        local ENTITY="$1"
        local NAME="$2"
        local UNIT="$3"
        local DEVICE_CLASS="$4"
        local VALUE_TEMPLATE="{{ value_json.$ENTITY }}"
        local TOPIC="$DISCOVERY_PREFIX/sensor/$DEVICE_ID/${ENTITY}/config"
        local PAYLOAD="{ \
            \"name\": \"$NAME\", \
            \"state_topic\": \"$STATE_TOPIC/${ENTITY}\", \
            \"unique_id\": \"${DEVICE_ID}_${ENTITY}\", \
            \"device\": { \
                \"identifiers\": [\"$DEVICE_ID\"], \
                \"manufacturer\": \"Pegasus Astro\", \
                \"model\": \"Pocket Powerbox Advance Gen2\", \
                \"name\": \"PPB Advance Gen2\" \
            }"

        # Optional fields
        if [ -n "$UNIT" ]; then
            PAYLOAD="$PAYLOAD, \"unit_of_measurement\": \"$UNIT\""
        fi
        if [ -n "$DEVICE_CLASS" ]; then
            PAYLOAD="$PAYLOAD, \"device_class\": \"$DEVICE_CLASS\""
        fi

        PAYLOAD="$PAYLOAD }"
        mosquitto_pub -h "$MQTT_HOST" -u "$MQTT_USER" -P "$MQTT_PASS" \
            -t "$TOPIC" -m "$PAYLOAD" -r
    }
    # Sensors
    publish_sensor "voltage"                "PPB Voltage"           "V"    "voltage"
    publish_sensor "current"                "PPB Current"           "A"    "current"
    publish_sensor "temperature"            "PPB Temperature"       "°C"   "temperature"
    publish_sensor "humidity"               "PPB Humidity"          "%"    "humidity"
    publish_sensor "dewPoint"               "PPB Dew Point"         "°C"   ""
    publish_sensor "averageAmps"            "PPB Average Amps"      "A"    ""
    publish_sensor "ampsPerHour"            "PPB Amps Per Hour"     "Ah"   ""
    publish_sensor "wattPerHour"            "PPB Watt Per Hour"     "Wh"   ""
    publish_sensor "upTime"                 "PPB Uptime"            ""     ""
    publish_sensor "powerHubStatus"         "PPB Power Hub Status"  ""     ""
    publish_sensor "powerVariablePortStatus" "PPB Variable Port"    ""     ""
    publish_sensor "ppbA_DualUSB2Status"    "PPB Dual USB2 Status"  ""     ""
  }
  publish_discovery
  exit
}

while [ -n "$1" ]; do
  case "$1" in
    -h|--help) do_help; shift 1;;
    --ip) PODip="$2"; shift 2;;
    --port) PODport="$2"; shift 2;;
    --init*) do_init; shift 1;;
    --start) do_start; shift 1;;
    --mqtt*) do_mqtt; shift 1;;
    --stat*) do_stats; shift 1;;
    --power) myCommand="power${2:-on}"; myDevice="$3"; shift 3;;
    --poweron) myCommand="poweron"; myDevice="$2"; shift 2;;
    --poweroff) myCommand="poweroff"; myDevice="$2"; shift 2;;
    -d|--debug) debug="true"; shift 1;;
    *) shift 1;;
  esac
done

case "$myCommand" in
  poweroff) do_poweroff;;
  poweron) do_poweron;;
#  *) do_help;;
esac

exit
