#!/bin/bash
#
# v0.1 - 26-Jan-04 - Initial Version for NSW only
# v0.5 -   -Oct-04 - Major cleanup
# v0.6 - 09-Nov-04 - Bug Fixes
# v0.7 - 11-Nov-04 - Corrected error with end time
# v0.8 - 10-Dec-04 - BOM changed format of VK2 warnings - Also added MP3 suport
# v0.9 - 13-Dec-04 - Error corrections
# v1.0 - 20-Jan-05 - Found a fix for the VK2 graphical warning problem
#
# v3.0 - 03-Jan-23 - Major rewrite and code review to use BOM AMOC XML, after years of, well...
#
# v3.1 - 06-Jan-24 - Added -saveaudio command line switch and added logging
#


#######################################################################
#
# Function definition
# The post-run cleanup function
cleanup() {
    rm -f $TMPDIR/temp.ul $TMPDIR/wavefile.ul $TMPDIR/areas $TMPDIR/stormlog
    if [ "$DEBUG" = false ]; then
        rm -f $TMPDIR/wavefile.wav $OUTFILE $TMPDIR/ID*.xml $TMPDIR/ID*.txt
    fi
}
#
# This function logs Date etc then message..
#
writelog() {
  MESSAGE="`date '+%b %d %Y %T'` "$@
  if [ -n "$LOGFILE" ]; then
    echo $MESSAGE >> $LOGFILE
  fi
}
#

#######################################################################
#
# Read in command-line args

if [ "$1" == "" ] ; then echo "You must define the state for this warning!" ; exit 0 ; fi
STATE=$1

if [ $(echo $@ | grep -c '\-debug') -eq 1 ]; then DEBUG=true; else DEBUG=false; fi
if [ $(echo $@ | grep -c '\-notx') -eq 1 ]; then NO_TX=true; else NO_TX=false; fi
if [ $(echo $@ | grep -c '\-local') -eq 1 ]; then PLAY_LOCAL=true; else PLAY_LOCAL=false; fi
if [ $(echo $@ | grep -c '\-tts') -eq 1 ]; then TTS=true; else TTS=false; fi
if [ $(echo $@ | grep -c '\-saveaudio') -eq 1 ]; then SAVEAUDIO=true; else SAVEAUDIO=false; fi

# Hard-code TTS to false for now
TTS=false

if [ "$DEBUG" = true ]; then
    echo; echo "-----------------Runtime: `date '+%b_%d_%Y_%T'`-----------------"
    echo "DEBUG: STATE="$STATE
fi

# Call the cleanup() function on any exit (ctrl-c etc)
trap cleanup EXIT

#######################################################################
#
#if [ "$DEBUG" = false ]; then
    # Make sure we are user repeater!!!
    if [ `/usr/bin/whoami` != "repeater" ] ; then
        echo This program must be run as user REPEATER!
        exit 1
    fi

    . /home/irlp/custom/environment

    # Make sure we have sourced the environment file
    if [ "$RUN_ENV" != "TRUE" ] ; then
        echo "You must source the environment file first. Do this by running:"
        echo ". /home/irlp/custom/environment"
        exit 1
    fi

    if [ ! -f $LOCAL/enable ] ; then exit 0 ; fi
    if [ -f $LOCAL/active ] ; then exit 0 ; fi
#else
#    CUSTOM=$(pwd)
#    AUDIO=/home/irlp/audio
#    BIN=/home/irlp/bin
#fi

################################################################################################
# Define the warning files to download
if [ "$STATE" == "vk1" ] ; then WARNING_LIST="IDN21033 IDN21036" ; STATE=vk2 ; fi
if [ "$STATE" == "vk2" ] ; then WARNING_LIST="IDN21033 IDN21035 IDN21036" ; fi
if [ "$STATE" == "vk3" ] ; then WARNING_LIST="IDV21033 IDV21035" ; fi
if [ "$STATE" == "vk4" ] ; then WARNING_LIST="IDQ21033 IDQ21035" ; fi
if [ "$STATE" == "vk5" ] ; then WARNING_LIST="IDS21033 IDS21035" ; fi
if [ "$STATE" == "vk6" ] ; then WARNING_LIST="IDW21033 IDW21034 IDW21035" ; fi
if [ "$STATE" == "vk7" ] ; then WARNING_LIST="IDT21033 IDT21035" ; fi
if [ "$STATE" == "vk8" ] ; then WARNING_LIST="IDD21033 IDD21034 IDD21035 IDD20590" ; fi

LOCLIST=$CUSTOM/stormcheck_locations.$STATE

################################################################################################
#

# If the node is active only play the warning areas, not the full TTS output
if [ -f $LOCAL/active ] ; then
    TTS=false
fi
if [ "$TTS" = true ]; then
    if [ ! -f $FESTPATH/text2wave ] ; then
        TTS=false
        echo "Festival is not installed, or not installed correctly - TTS will not be done"
    fi
fi

# Initialise some of the variables set within the script
STORMAUDIO=$AUDIO/custom/stormcheck
USE_AUS_TIME_AUDIO=true
TMPDIR=/tmp
NOWARN=TRUE
STORMLOG=/tmp/stormlog
WARN_LOOP=0

# loop through the warning files for the defined state
for WARNING_FILE in $WARNING_LIST ; do
    unset DISPLIST
    unset LOC_PLAYLIST
    #  Download the warning pages
    WARNING_URL=ftp://ftp.bom.gov.au/anon/gen/fwo
    WARNING_FILE1=$WARNING_FILE.amoc.xml
    WARNING_FILE2=$WARNING_FILE.txt
    WARNING_FILE3=$WARNING_FILE.xml

    if [ "$DEBUG" = true ]; then echo; echo "DEBUG: Processing $WARNING_FILE1"; fi
    wget -qO $TMPDIR/$WARNING_FILE1 $WARNING_URL/$WARNING_FILE1
    wget -qO $TMPDIR/$WARNING_FILE2 $WARNING_URL/$WARNING_FILE2
    wget -qO $TMPDIR/$WARNING_FILE3 $WARNING_URL/$WARNING_FILE3
    if [ $(ls -1 $TMPDIR | grep -c ^$WARNING_FILE1$) -ne 1 ]; then
        if [ "$DEBUG" = true ]; then echo "DEBUG: $WARNING_FILE1 is not available - no warnings there"; fi
        continue
    fi
    if [ $(stat -c %b $TMPDIR/$WARNING_FILE1) -eq 0 ]; then
        if [ "$DEBUG" = true ]; then echo "DEBUG: $WARNING_FILE1 is not available - no warnings there"; fi
        continue
    fi

    ################################################################################
    # Extract the validity time from the AMOC XML
    START=$(cat $TMPDIR/$WARNING_FILE1 | grep validity-bgn-time-local | grep -oP '<v.*>\K.*?(?=</.*)')
    END=$(cat $TMPDIR/$WARNING_FILE1 | grep validity-end-time-local | grep -oP '<v.*>\K.*?(?=</.*)')
    HEADLINE=$(cat $TMPDIR/$WARNING_FILE1 | grep headline | grep -oP '<head.*>\K.*?(?=</.*)' | grep -iv cancel)

    if [ "$DEBUG" = true ]; then
        echo "DEBUG: START = $START"
        echo "DEBUG: END   = $END"
        echo "DEBUG: HEADLINE = $HEADLINE"
    fi

    # Does the current time fall within the validity window?
    # Convert timestamps from ISO-8601 format to Epoch to compare numerically with the current time
    StartEpoch=$(date -d $START +"%s")
    EndEpoch=$(date -d $END +"%s")
    if [ $(date +"%s") -gt $StartEpoch ] && [ $(date +"%s") -lt $EndEpoch ]; then
        if [ "$DEBUG" = true ]; then echo "DEBUG: Current time is inside warning validity period"; fi
    else
        # Current time is outside warning validity - skip and process the next item
        if [ "$DEBUG" = true ]; then echo "DEBUG: Current time is outside warning validity period"; fi
        continue
    fi

    # Extract the warning_phenomena_summary from the XML
    PHENOMENA=$(cat $TMPDIR/$WARNING_FILE3 | sed -n -e '/<text type="warning_phenomena_summary">/,/<\/text>/p' | grep -v text | sed -e 's/<[^>]*>//g')
    if [ "$DEBUG" = true ]; then echo "DEBUG: RAW Phenomena = $PHENOMENA"; fi

    #################################################################################
    # Build an array containing the areas affected by this warning
    cat $TMPDIR/$WARNING_FILE1 | grep 'area aac' > /tmp/areas
    WARNCOUNT=0
    while read -r AREA; do
        AREA_AAC=$(echo $AREA | cut -f2 -d\")
        AREA_PHASE=$(echo $AREA | cut -f4 -d\")
        AREA_DESC=$(echo $AREA | cut -f6 -d\")
        # Ignore bogus areas
        # if [ $(echo "$AREA_AAC" | grep -c "_SP001") -ne 0 ]; then
        if [ "$AREA_AAC" != "NSW_SP001" ] && [ "$AREA_AAC" != "QLD_SP001" ] && [ "$AREA_AAC" != "VIC_SP001" ]; then
            if [ "$AREA_PHASE" == "CAN" ]; then
                if [ "$DEBUG" = true ]; then echo "DEBUG: Warning cancelled for "$AREA_AAC" ("$AREA_DESC")"; fi
            else
                if [ "$DEBUG" = true ]; then echo "DEBUG: Warning current for "$AREA_AAC" ("$AREA_DESC")"; fi
                WARNCOUNT=$(expr $WARNCOUNT + 1)
                # Check if the active warning areas match our selectors
                if [ $(grep -c ^$AREA_AAC $CUSTOM/stormcheck_locations.$STATE) -ne 0 ]; then
                    NOWARN=FALSE
                    AREA_FILE=$(echo $AREA_DESC | tr ' ' '_' | tr '/' '_' | tr '-' '_')
                    DISPLIST="$DISPLIST $AREA_DESC"
                    LOC_PLAYLIST="$LOC_PLAYLIST $STORMAUDIO/$AREA_FILE"
                fi
            fi
        fi
    done < /tmp/areas

    # If we haven't found a warning of interest to us, skip to the next input file.
    if [ $WARNCOUNT -eq 0 ]; then
        if [ "$DEBUG" = true ]; then echo "No warnings of interest"; fi
        continue
    fi

    # Start building out variables to use when building audio playlist
    WARN_LOOP=$(expr $WARN_LOOP + 1)
    ISSUE_HOUR=$(date -d $START +"%l" | xargs)
    ISSUE_MIN=$(date -d $START +"%M")
    ISSUE_AMPM=$(date -d $START +"%p" | tr '[:upper:]' '[:lower:]')
    #
    WARN_END_HOUR=$(date -d $END +"%l" | xargs)
    WARN_END_MIN=$(date -d $END +"%M")
    WARN_END_AMPM=$(date -d $END +"%p" | tr '[:upper:]' '[:lower:]')

    if [ "$DEBUG" = true ]; then
        echo "####### DEBUG #######"
        echo "Issue Time = $ISSUE_HOUR:$ISSUE_MIN $ISSUE_AMPM"
        echo "Warn End Hour = $WARN_END_HOUR"
        echo "Warn End Minute = $WARN_END_MIN"
        echo "Warn End AMPM = $WARN_END_AMPM"
    fi

    # If we want TTS for the entire warning we need to handle that here
    if [ "$TTS" = true ] ; then
        echo "DEBUG: Parse $TMPDIR/$WARNING_FILE2 downloaded here..."
        # generates TTS_AUDIO
    fi

    # Build the list of forcast conditions (phenomena)
    PHENOM_STRING=
    if [ $(echo $PHENOMENA | grep -ic 'damaging wind') -eq 1 ]; then PHENOM_STRING="$PHENOM_STRING damaging_winds"; fi
    if [ $(echo $PHENOMENA | grep -ic 'destructive wind') -eq 1 ]; then PHENOM_STRING="$PHENOM_STRING destructive_winds"; fi
    if [ $(echo $PHENOMENA | grep -ic 'large hail') -eq 1 ]; then PHENOM_STRING="$PHENOM_STRING large_hailstones"; fi
    if [ $(echo $PHENOMENA | grep -ic 'giant hail') -eq 1 ]; then PHENOM_STRING="$PHENOM_STRING giant_hailstones"; fi
    if [ $(echo $PHENOMENA | grep -ic 'heavy rainfall') -eq 1 ]; then PHENOM_STRING="$PHENOM_STRING heavy_rainfall"; fi
    if [ $(echo $PHENOMENA | grep -ic 'intense rain') -eq 1 ]; then PHENOM_STRING="$PHENOM_STRING intense_rainfall"; fi

    #############################################################################
    # Output the results
    #
    echo "" > $STORMLOG
    echo "Warning for: "$DISPLIST >> $STORMLOG
    echo "Phenomena: "$PHENOM_STRING >> $STORMLOG
    echo "Issued at: "$ISSUE_HOUR $ISSUE_MIN $ISSUE_AMPM >> $STORMLOG
    if [ "$WARN_END_HOUR" != "" ] && [ "$WARN_END_MIN" != "" ] ; then
    echo "Valid until: "$WARN_END_HOUR $WARN_END_MIN $WARN_END_AMPM >> $STORMLOG

    fi
    echo "" >> $STORMLOG
    if [ "$TTS" = "YES" ] ; then cat $OUTFILE >> $STORMLOG; fi

    if [ "$DEBUG" = true ]; then
        echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
        cat $STORMLOG
        echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
    fi

    if [ "$USE_AUS_TIME_AUDIO" = true ]; then
        ISSUE_HOUR=$(echo ${ISSUE_HOUR}_aus)
        ISSUE_MIN=$(echo ${ISSUE_MIN}_aus)
        ISSUE_AMPM=$(echo ${ISSUE_AMPM}_aus)
        WARN_END_HOUR=$(echo ${WARN_END_HOUR}_aus)
        WARN_END_MIN=$(echo ${WARN_END_MIN}_aus)
        WARN_END_AMPM=$(echo ${WARN_END_AMPM}_aus)
    fi

    #############################################################################
    # Build the strings of audio files for playing
    #
    # If this is the first warning in the loop play the initial preambles.
    if [ "$WARN_LOOP" == "1" ]; then
        PLAYSTRING="$STORMAUDIO/klaxon"
        PREAMBLE_FILE="$STORMAUDIO/severe_ts"
    else
        PREAMBLE_FILE="$STORMAUDIO/severe_ts2"
    fi

    # Build out the playlists
    PLAYSTRING="$PLAYSTRING $PREAMBLE_FILE $LOC_PLAYLIST \
        $STORMAUDIO/issuedat $AUDIO/custom/$ISSUE_HOUR $AUDIO/custom/$ISSUE_MIN $AUDIO/custom/$ISSUE_AMPM"

    NEXTWARN_STRING="$STORMAUDIO/nextwarn $AUDIO/custom/$WARN_END_HOUR $AUDIO/custom/$WARN_END_MIN \
        $AUDIO/custom/$WARN_END_AMPM"

    # Build the forcast phenomena playlist
    PHENOMENA_STRING="$STORMAUDIO/phenom_preamble"
    for condition in $PHENOM_STRING; do
        PHENOMENA_STRING="$PHENOMENA_STRING $STORMAUDIO/$condition"
    done
    PHENOMENA_STRING="$PHENOMENA_STRING $STORMAUDIO/phenom_post"

    # Put the strings together to form the complete announcement
    if [ "$STD_WARN" == "YES" ] || [ "$TTS" = false ]; then
        PLAYSTRING="$PLAYSTRING $PHENOMENA_STRING $NEXTWARN_STRING"
    elif [ "$TTS" = true ]; then
        PLAYSTRING="$PLAYSTRING $TTS_AUDIO $NEXTWARN_STRING"
    else
        PLAYSTRING="$PLAYSTRING $PHENOMENA_STRING $NEXTWARN_STRING"
    fi

done

# Decide if we need to continue
if [ "$NOWARN" == "TRUE" ]; then
    if [ "$DEBUG" = true ]; then echo "DEBUG: No warnings of interest - exiting"; fi
    writelog "Stormcheck: No warnings of interest."
    rm -f $TMPDIR/*.xml
    exit 0
fi

if [ "$DEBUG" = true ]; then echo "DEBUG: $PLAYSTRING"; fi


#################################################################################
# Munge the output audio together
#
if [ -f /usr/bin/sox ] ; then
    rm -f $TMPDIR/wavefile.ul
    for FILE in $PLAYSTRING ; do
        if [ ! -f $FILE.ul ] ; then
            rm -f $TMPDIR/temp.ul
            /usr/bin/sox $FILE.wav $TMPDIR/temp.ul
            cat $TMPDIR/temp.ul >> $TMPDIR/wavefile.ul
        else
            cat $FILE.ul >> $TMPDIR/wavefile.ul
        fi
    done
    # Output wav format must be Microsoft PCM (-e un), 8000kHz (-r 8000) Mono (-c 1).
    /usr/bin/sox -r 8000 -c 1 $TMPDIR/wavefile.ul -e un $TMPDIR/wavefile.wav
    WAVFILES="$TMPDIR/wavefile.wav"
else
    for FILE in $PLAYSTRING ; do
        WAVFILES="$WAVFILES $FILE.wav"
    done
fi

if [ "$SAVEAUDIO" = true ]; then
   NOW="`date '+%b_%d_%Y_%T' | sed 's/://g'`"
   if [ ! -d $AUDIO/custom/stormaudio ]; then
       mkdir $AUDIO/custom/stormaudio
   fi
   cp $TMPDIR/wavefile.wav $AUDIO/custom/stormaudio/$NOW"_stormaudio.wav"
   if [ "$DEBUG" = true ]; then echo "DEBUG: Saved Audio File"; fi
fi

#######################################################################
# Initiate the playback
#
if [ "$NOWARN" != "TRUE" ] ; then
    if [ "$NO_TX" = true ]; then
        if [ "$PLAY_LOCAL" = true ]; then
            play $WAVFILES
        fi
    fi

    ################
    if [ "$NO_TX" = false ]; then
        if [ -f $LOCAL/active ] ; then
            killall -9 ispeaker >&/dev/null 2>&1
            killall -9 ispeaker_PCI >&/dev/null 2>&1
            killall -9 sfswrapper >&/dev/null 2>&1
        fi

        $BIN/coscheck
        $BIN/coscheck
        $BIN/coscheck
        $BIN/coscheck
        $BIN/coscheck
        $BIN/coscheck
        $BIN/coscheck
        $BIN/coscheck
        $BIN/coscheck
        $BIN/coscheck
        $BIN/forcekey
        sleep 2
        $BIN/play $WAVFILES >/dev/null 2>&1
        sleep 2
        $BIN/forceunkey
        writelog "Stormcheck: Weather Warning Transmitted"
        if [ -f $LOCAL/active ]; then "$SCRIPT"/sfswrapper; fi
    fi
fi

exit 0
