#!/bin/ksh

RUN_DIR=$(cd -- "$(dirname "$0")" && pwd)
PATH=$RUN_DIR:/usr/local/bin/:$PATH ; export PATH
. ac_common
WE_ARE=$( basename "$0" )

running_mode=$(echo $0 | sed 's/.*_//')

set -m   # even though we've double forked, don't want any chance the
         # apache process still thinks its the session leader of us
         # and kills our children when apache restarts

#echo "Ignoring traps until we have set up since we don't want to kill our competitor only to find we've been killed before forking ourselves"
for i in INT QUIT TERM HUP PIPE ; do 
    trap "echo $WE_ARE[\$\$]: ignore -SIG$i: `date`" $i
done

selectval() {
    echo "$met" | grep "^$1 " | awk '{print $2}'
}

poll_temp() {
#    echo "`date`: Entering poll_temp"
# first bunch of readings are from the wall clock, whereas others are from 1wire sensors with short response time
    met=`timeout 10 wget --quiet --no-proxy -O- http://pi/~tconnors/weather/met.data`
    read_time=`selectval ReadTime`
    age=$((`date +%s` - ${read_time:-0}))
    if [ $age -gt 1800 ] ; then
        outdoor_temp=NA
        study_temp=NA
        bedroom_temp=NA
        loungeroom_temp=NA
        fridge_temp=NA
#        warmbeerfridge_temp=NA
#        coolbeerfridge_temp=NA
#        brewfridge_temp=NA
        winddir=NA
        windspeed=NA
        windgust=NA
        humidity=NA
        pressure=NA
        rr=NA
        r24h=NA
    else
        outdoor_temp=`selectval To`
        study_temp=`selectval Ti`
        bedroom_temp=`selectval TBR`
        loungeroom_temp=`selectval TLR`
        fridge_temp=`selectval TFridge`
#        warmbeerfridge_temp=`selectval TWarmBeerFridge`
#        coolbeerfridge_temp=`selectval TCoolBeerFridge`
#        brewfridge_temp=`selectval TBrewFridge`
        winddir=`selectval DIRtext`
        windspeed=`selectval WS`
        windgust=`selectval WG`
        humidity=`selectval RHo`%
        pressure=`selectval RP` ; pressure=`printf "%.1f" "$pressure"`
        rr=`selectval Rr`
        r24h=`selectval R24h`
    fi

    t=$(grep -A1 crc=.*YES /sys/bus/w1/devices/28-000006dd703c/w1_slave 2>/dev/null | sed -n 's/.*t=//p')
    if [ -n "$t" ] ; then
        pi_temp1=$(bc <<< "scale=2 ; $t/1000")
    fi

    t=$(grep -A1 crc=.*YES /sys/bus/w1/devices/28-000006dd25c4/w1_slave 2>/dev/null | sed -n 's/.*t=//p')
    if [ -n "$t" ] ; then
        pi_temp2=$(bc <<< "scale=2 ; $t/1000")
    fi
    atomic_write --overwrite $CURRENT_TEMP_FILE "$current_temp"
    atomic_write --overwrite $STUDY_TEMP_FILE "$study_temp"
    atomic_write --overwrite $BEDROOM_TEMP_FILE "$bedroom_temp"
    atomic_write --overwrite $LOUNGEROOM_TEMP_FILE "$loungeroom_temp"
    atomic_write --overwrite $OUTDOOR_TEMP_FILE "$outdoor_temp"
    atomic_write --overwrite $FRIDGE_TEMP_FILE "$fridge_temp"
#    atomic_write --overwrite $WARMBEERFRIDGE_TEMP_FILE "$warmbeerfridge_temp"
#    atomic_write --overwrite $COOLBEERFRIDGE_TEMP_FILE "$coolbeerfridge_temp"
#    atomic_write --overwrite $BREWFRIDGE_TEMP_FILE "$brewfridge_temp"
    atomic_write --overwrite $PI_TEMP1_FILE "$pi_temp1"
    atomic_write --overwrite $PI_TEMP2_FILE "$pi_temp2"

    atomic_write --overwrite $WINDDIR_FILE "$winddir"
    atomic_write --overwrite $WINDSPEED_FILE "$windspeed"
    atomic_write --overwrite $WINDGUST_FILE "$windgust"

    atomic_write --overwrite $HUMIDITY_FILE "$humidity"
    atomic_write --overwrite $PRESSURE_FILE "$pressure"

    atomic_write --overwrite $RR_FILE "$rr"
    atomic_write --overwrite $R24H_FILE "$r24h"
}

sanity_check_arg() {
    cmd="$1"
    subcmd="$2"
    case "$cmd" in
        disable|enable)
            case "$subcmd" in
                until|after|"")
                    ;;
                *)
                    echo "Keh?  Can't undestand $cmd subcmd '$subcmd'"
                    return 1
                    ;;
            esac
            ;;
        "")
            ;;
        *)
            echo "Unknown cmd $cmd"
            return 1
            ;;
    esac
}

gather_cmd() {
#    echo "`date`: Entering gather_cmd"
    cmd=$(atomic_read $CMD_FILE)
    read cmd subcmd time < <(echo "$cmd")
    if [ -n "$time" ] ; then
        humantime=$(date -d "$time")
        if [ -z "$humantime" ] ; then
            echo "Can't parse date: $time"
            return 1
        fi
        daynum=$(date +%-d -d "$time")
        time=$(date +%s -d "$time")
    else
        daynum=$(date +%-d)
        humantime="now: ($(date))"
    fi
    sanity_check_arg "$cmd" "$subcmd" || (echo "Sanity check failed on $cmd $subcmd" ; return 1 )
    case "$cmd" in
        disable|enable) #FIXME: add a flag either here, to turn off/on instead of disable/enable.  logically, it belongs on TIMER_STATE_FILE.  But if it was associated with DESIRED_STATE_FILE, it could override the settings in that correctly, 
            atomic_write --overwrite $TIMER_STATE_FILE "$cmd $subcmd $time # $humantime"
            cal -c | colorgrep -p --colour green "\\b${daynum}\\b" | sed '/^ *$/d'
            echo "setting: $cmd $subcmd $humantime"
            ;;
        "")
            :
            ;;
    esac
}

set_ac_per_preset() {
    desired_state=$(atomic_read --no-rm $DESIRED_STATE_FILE)
    atomic_write --overwrite $STATE_FILE "$desired_state # from DESIRED_STATE"
    if echo "$desired_state" | grep -q ^on ; then
        ac_thermostat_control on ${running_mode}
        [ "$1" = --updatetimerstate ] && 
          atomic_write --overwrite $TIMER_STATE_FILE "enable"
    fi
    if echo "$desired_state" | grep -q ^off ; then
        ac_thermostat_control off ${running_mode}
        [ "$1" = --updatetimerstate ] && 
          atomic_write --overwrite $TIMER_STATE_FILE "disable"
    fi
}

handle_cmd() {
#    echo "`date`: Entering handle_cmd"
    cmd=$(atomic_read --no-rm $TIMER_STATE_FILE)
    read cmd subcmd time < <(echo "$cmd")
    now=$(date +%s)
    sanity_check_arg "$cmd" "$subcmd" || return 1
    case "$cmd" in
        disable)
            case "$subcmd" in
                until)
                    if [ $now -gt $time ] ; then
                        #want to make "disable until" not actually
                        #turn on the power - just stop it from being
                        #disabled.  This diffes logically from all
                        #other calls
                        #set_ac_per_preset --updatetimerstate
                        atomic_write --overwrite $TIMER_STATE_FILE "disable # timer expired"
                    else
                        turn_off_ac --updatestate --noreset
                    fi
                    ;;
                after)
                    if [ $now -gt $time ] ; then
                        turn_off_ac --updatetimerstate --updatestate --noreset
                    else
                        set_ac_per_preset
                    fi
                    ;;
                "")
                    turn_off_ac --updatestate --noreset
                    ;;
            esac
            ;;
        enable)
            case "$subcmd" in
                until)
                    if [ $now -gt $time ] ; then
                        turn_off_ac --updatetimerstate --updatestate --noreset
                    else
                        set_ac_per_preset
                    fi
                    ;;
                after)
                    if [ $now -gt $time ] ; then
                        set_ac_per_preset --updatetimerstate
                    else
                        turn_off_ac --updatestate --noreset
                    fi
                    ;;
                "")
                    set_ac_per_preset
                    ;;
            esac
            ;;
        "")
            :
            ;;
    esac
}

run_daemon() {
    read -r BASHPID _ </proc/self/stat  # $$ never fixed in subshells, but bash comes with BASHPID.  Can be faked in ksh, possibly others...

    for i in INT QUIT TERM HUP PIPE ; do 
        trap "trap - $i ; echo $WE_ARE[\$BASHPID]: We was KILLED -SIG$i: \`date\` ; kill -$i \$BASHPID ; ( date ; ps axfu ) >&2 ; exit " $i
    done
    trap 'EXIT=$? ; trap - 0 ; echo "$WE_ARE[$BASHPID]: EXIT($EXIT): `date`" ; ( date ; ps axfu ) >&2 ; exit $EXIT' 0

    echo "$WE_ARE[$$->$BASHPID]: loop starting, have forked, have set up traps: `date`"

    echo $BASHPID $(date +%s) > $PIDFILE
#    echo $$ $(date +%s) > $PIDFILE

    while : ; do
        grep -q $running_mode $MODE_FILE || exit

        if [ "$needopenlog" = true ] ; then
            # now that we've sent our first output to the terminal, allow the
            # daemon to daemonise properly
            logfile=/var/log/${running_mode}.log
            errfile=/var/log/${running_mode}.err
            echo Reopening $logfile: `date`
            exec >> $logfile 2>> $errfile
            ls -lA /proc/$BASHPID/fd/ >&2
            needopenlog=false
            ps $BASHPID
            ( date ; ps axfu ) >&2
            ( run_daemon ) &
            return
        fi

        gather_cmd && handle_cmd
        poll_temp
#        echo $(date): sleeping...
        if [ -z "$needopenlog" ] ; then
            needopenlog=true
        else
            sleep 10
        fi
    done
}

check_daemon_running() {
    if [ -e $PIDFILE ] ; then
        read pid started < $PIDFILE
        if ps $pid > /dev/null ; then
#            echo -n "Re"
            kill $pid ; sleep 0.1 ; kill -9 $pid 2>/dev/null
        fi
#            filetime=$(stat -c %Y "$RUN_DIR/$CMD")
#            if [ "$filetime" -gt "$started" ] ; then
#            echo -n "."
#                atomic_write --overwrite $CMD_FILE quit
#                sleep 1
#            else
#                return
#            fi
    fi
#    echo "Starting..."
    if [ "$1" = --quiet ] ; then
        needopenlog=true
        shift
    fi
    if [ $# = 0 ] ; then
        run_daemon &
    elif [ "$1" != --kill ] ; then
        echo "Usage: $0 [--kill]" 1>&2
        exit 1
    fi
}

if [ $HOSTNAME != pi ] ; then
    exec ssh pi "$0" "$@" < /dev/null
fi

exec 2>&1

check_daemon_running "$@" < /dev/null

wait
