#!/bin/bash
# by Andre LaBranche, dre@mac.com

# This script plays a sound file when the user receives an iCal push
# notification. To customize the sound that is played, simply place the desired
# sound file in the 'sounds' directory.

# LaunchApps plist entry looks like:
#    NodeName = Dict {
#        ExecPath = /path/to/exec
#    }

PB="/usr/libexec/PlistBuddy"

# This is the audio volume level. 0 - 1 float.
VOLUME=".7"

checkLaunchApps() {
    # Check the AOSNotification settings to make sure the entry needed by this
    # script is present.
    echo "Checking for our entry in the push plist:"
    if ( $PB -c "print LaunchApps" "$PLIST"\
        | grep "CalDAV" > /dev/null)
    then
        # Entry is present...
        echo "   ... Found our CalDAV LaunchApps entry!"
        echo ""
        # ... but is it correct?
        verifyExecPath
    else
        # Entry is missing...
        echo "   ... Did not find our CalDAV LaunchApps entry."
        echo ""
        # ... so go make one!
        createLaunchAppsEntry
    fi
}

findAOSNplist() {
    # Locate the com.apple.AOSNotification property list. Because this plist is
    # host-specific, we'll aim for the most recently modified and hope it's the
    # right one.
    echo "Finding user's push notification property list:"
    PLIST=$(ls -1tr "$HOME/Library/Preferences/ByHost" | grep "AOSN")
    echo "   ... Found plist $PLIST"
    PLIST="$HOME/Library/Preferences/ByHost/$PLIST"
    echo ""
}

findCalDAVNode() {
    # Get this user's CalDAV XMPP node name
    echo "Finding user's CalDAV node name:"
    NODE=$($PB -c "print Subscriptions" "$PLIST"\
      | grep "nodeName" | grep "CalDAV" | awk '{print $3}')
    if [[ $NODE == "" ]]
    then
        echo -n "   ... Can't find user's push notification node."
        echo "   ... Be sure push is working in iCal."
        exitMe
    else
        echo "   ... Found user's node: $NODE"
    fi
    echo ""
}

verifyExecPath() {
    # Verify that the ExecPath value is equivalent to the current location of
    # this script.
    echo "Verifying ExecPath:"
    EXECPATH=$($PB -c "print LaunchApps:$NODE:ExecPath" $PLIST)
    echo "   ... current ExecPath value is: $EXECPATH"
    if [[ $EXECPATH != $script_path ]]
    then
        echo "   ... ExecPath does not match $script_path"
        echo "   Updating ExecPath to match:"
        if ( $PB -c "set LaunchApps:$NODE:ExecPath $script_path" $PLIST) 
        then
            echo "      ... ExecPath updated successfully!"
            BLOODTHIRSTY=1              # set a flag to restart aosnotifyd
        else
            echo "      ... failed to update ExecPath. Sounds won't play :/"
        fi
    else
        echo "   ... ExecPath is up to date!"
    fi
}

createLaunchAppsEntry() {
    # The AOSNotification settings we need are not present. Create them.
    echo "Creating a LaunchApps entry in $PLIST:"
    #echo $PB -c "add LaunchApps:$NODE dict" "$PLIST"
    #echo $PB -c "add LaunchApps:$NODE:ExecPath string $script_path" "$PLIST"
    if ( $PB -c "add LaunchApps:$NODE dict" "$PLIST" && \
         $PB -c "add LaunchApps:$NODE:ExecPath string $script_path" "$PLIST" )
    then
        echo "   ... Plist successfully modified!"
        BLOODTHIRSTY=1                  # set a flag to restart aosnotifyd
    else
        echo "   ... Plist modification failed! Sorry..."
        exitMe
    fi
    echo ""
}

killAosnotifyd() {
    if [ $BLOODTHIRSTY ] 
    then
        if ( ps auxww | grep aosnotifyd | grep -v grep > /dev/null )
        then
            killall aosnotifyd
            echo ""
            echo "Quit and relaunch iCal to complete the changes!"
        fi
    fi
}

testSound() {
    echo ""
    echo -n "Testing sound $sound_file in 5 seconds: "
    jot 5 1 | while read i ; do echo -n "." ; sleep 1 ; done
    playSound
    echo "Test Concluded."
}


exitMe() {
    # In case the user has Terminal configured to close cleanly on exit, we'll
    # hang around a sec to give them a second to read our output
    echo ""
    echo "All done. Exiting in 10 seconds."
    sleep 10
    exit
}

playSound() {
    /usr/bin/afplay -v $VOLUME $sound_file
}

unInstall() {
    echo "Uninstalling..."
    if ( $PB -c "print :LaunchApps:$NODE" "$PLIST" &> /dev/null )
    then
        if ( $PB -c "delete :LaunchApps:$NODE" "$PLIST" )
        then
            echo "   ... PingMe configuration successfully disabled!"
        else
            echo "   ... Found PingMe configuration, but couldn't delete it".
            echo ""
            echo "MANUAL UNINSTALLATION PROCEDURE"
            echo "Remove the file $PLIST and log out, or kill aosnotifyd"
        fi
    else
        echo "   ... didn't find any PingMe configuration to remove!"
    fi
}

# Preflight things
# Verify that the path to ourself is coherent. The app launching mechanism
# of aosnotifyd does not appear to support spaces in the ExecPath
script_path="$( cd $(/usr/bin/dirname "${BASH_SOURCE[0]}")
                pwd -P)/$(/usr/bin/basename "${BASH_SOURCE[0]}")"
[[ ! -f "$script_path" ]] && \
   script_path="$(cd $(/usr/bin/dirname "$0");pwd -P)/$(/usr/bin/basename "$0")"
[[ ! -f "$script_path" ]] && \
   script_path="" && echo 'No spaces in our path, please!' && exit 1
# echo "script path is $script_path"

# Find the sound file to use
sound_file=$(find $(dirname $script_path)/sounds -type f -depth 1 | tail -n 1)
# echo "sound path is $sound_file"
if [[ ! -f $sound_file ]]
   then
   echo "Could not find sound file! Be sure there is an adjacent 'sounds'"
   echo "directory with at least one sound file in it."
   exitMe
fi

# When this script is executed by aosnotifyd, the first argument is always
# --notified. We use this to decide whether to play the sound file or to create
# or update the PushMe configuration. To test the sound playback, you can run
# the script from a Terminal with that argument, e.g. 
# /path/to/PushMe.sh --notified
if [[ $1 == "--notified" ]]
then
    playSound
else
    if [[ $1 == "--uninstall" ]]
    then
        findAOSNplist
        findCalDAVNode
        unInstall
        exitMe
    else
        findAOSNplist
        findCalDAVNode
        checkLaunchApps
        killAosnotifyd
        testSound
        exitMe
    fi
fi
