set done to false
repeat until done
	display dialog "This applet can be used to make sure that a connected drive never goes to sleep (that is, that it never spins down). Normally this can be controlled using the Energy Saver preference pane in System Preferences, but some external drives do not respect these settings." & return & return & "This applet simply creates a launch agent that tells OS X to update a hidden file on the selected drive once every minute so that the drive stays active. Launch agents persist across reboots, etc., so you can run this once to set-it-and-forget-it." & return & return & "To keep more than one drive awake, run this applet again and select another drive from the list." & return & return & "To stop keeping a drive awake, click on Let a drive sleep... or just go to " & POSIX path of (((path to library folder from user domain) as text) & "LaunchAgents") & " and delete the file net.jonstovell.keep<DriveName>Spinning.plist (where <DriveName> is the name of the drive)." buttons {"Quit", "Let a drive sleep...", "Keep a drive awake..."} default button "Keep a drive awake..." with icon note with title "Keep Drive Spinning"
	if button returned of result is "Keep a drive awake..." then
		try
			set sleepless to {}
			tell application "System Events" to set vols to name of every disk whose free space is not 0
			set selected to choose from list vols with prompt "Choose a drive to keep awake." & return & "Press Shift for multiple items." with title "Keep Drive Spinning" with multiple selections allowed
			if selected is false then
				error number -128
			else
				repeat with i from 1 to count selected
					set sel to item i of selected
					
					set ASTID to AppleScript's text item delimiters
					
					-- Escape XML reserved characters in sel
					set AppleScript's text item delimiters to "&"
					set sel_xmlsafe to text items of sel
					set AppleScript's text item delimiters to "&amp;"
					set sel_xmlsafe to sel_xmlsafe as text
					set AppleScript's text item delimiters to ">"
					set sel_xmlsafe to text items of sel_xmlsafe
					set AppleScript's text item delimiters to "&gt;"
					set sel_xmlsafe to sel_xmlsafe as text
					set AppleScript's text item delimiters to "<"
					set sel_xmlsafe to text items of sel_xmlsafe
					set AppleScript's text item delimiters to "&lt;"
					set sel_xmlsafe to sel_xmlsafe as text
					
					-- Get a version of sel with no spaces
					set AppleScript's text item delimiters to space
					set sel_nospace to text items of sel
					set AppleScript's text item delimiters to ""
					set sel_nospace to sel_nospace as text
					
					-- Escape XML reserved characters in sel_nospace
					set AppleScript's text item delimiters to "&"
					set sel_nospace_xmlsafe to text items of sel_nospace
					set AppleScript's text item delimiters to "&amp;"
					set sel_nospace_xmlsafe to sel_nospace_xmlsafe as text
					set AppleScript's text item delimiters to ">"
					set sel_nospace_xmlsafe to text items of sel_nospace_xmlsafe
					set AppleScript's text item delimiters to "&gt;"
					set sel_nospace_xmlsafe to sel_nospace_xmlsafe as text
					set AppleScript's text item delimiters to "<"
					set sel_nospace_xmlsafe to text items of sel_nospace_xmlsafe
					set AppleScript's text item delimiters to "&lt;"
					set sel_nospace_xmlsafe to sel_nospace_xmlsafe as text
					
					set AppleScript's text item delimiters to ASTID
					
					set {interval, b} to {text returned, button returned} of (display dialog "How often (in seconds) should OS X prod " & sel & " to keep it awake?" default answer "60" with icon note with title "Keep Drive Spinning")
					
					set plisttext to "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
                            <!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"
                            \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
                            <plist version=\"1.0\">
                            <dict>
                            <key>Label</key>
                            <string>net.jonstovell.keep" & sel_nospace_xmlsafe & "Spinning</string>
                            <key>ProgramArguments</key>
                            <array>
                            <string>/bin/bash</string>
                            <string>-c</string>
                            <string>if [[ -e /Volumes/" & quoted form of sel_xmlsafe & "/.keepThisDriveSpinning ]]; then date &gt; /Volumes/" & quoted form of sel_xmlsafe & "/.keepThisDriveSpinning; fi</string>
                            </array>
                            <key>RunAtLoad</key>
                            <true/>
                            <key>StartInterval</key>
                            <integer>" & interval & "</integer>
                            </dict>
                            </plist>"
					
					-- Make sure plisttext is valid XML so we don't get a broken launch agent. Also make it pretty while we are at it.
					try
						set plisttext to (do shell script "echo " & quoted form of plisttext & " | xmllint --format -")
					on error errMsg number errNum
						error "Could not create a valid launch agent for " & sel number errNum
					end try
					
					-- Create the hidden file on the drive
					try
						do shell script "touch /Volumes/" & quoted form of sel & "/.keepThisDriveSpinning"
					on error errMsg number errNum
						if errMsg contains "Permission denied" then
							display dialog "Your user does not have permission to create the necessary file in " & sel & ". Retry with an administrator password?" & return & return & "You will only need to do this once." buttons {"Cancel", "Retry"} with icon caution with title "Keep Drive Spinning"
							if button returned of result is "Retry" then do shell script "touch /Volumes/" & quoted form of sel & "/.keepThisDriveSpinning; chmod 777 /Volumes/" & quoted form of sel & "/.keepThisDriveSpinning" with administrator privileges
						else
							error errMsg number errNum
						end if
					end try
					
					-- If there is an old version of the launch agent already in memory, unload and delete it
					do shell script "launchctl unload -w ~/Library/LaunchAgents/net.jonstovell.keep" & quoted form of sel_nospace & "Spinning.plist"
					do shell script "rm -f ~/Library/LaunchAgents/net.jonstovell.keep" & quoted form of sel_nospace & "Spinning.plist"
					
					-- Create the launch agent
					do shell script "mkdir -p ~/Library/LaunchAgents; echo " & quoted form of plisttext & " > ~/Library/LaunchAgents/net.jonstovell.keep" & quoted form of sel_nospace & "Spinning.plist"
					
					-- Load the launch agent
					do shell script "launchctl load -w ~/Library/LaunchAgents/net.jonstovell.keep" & quoted form of sel_nospace & "Spinning.plist"
					
					-- Double check that it loaded properly
					set agentloaded to false
					repeat 4 times
						if (do shell script "launchctl list") does not contain "net.jonstovell.keep" & sel_nospace & "Spinning" then
							delay 0.5
						else
							set agentloaded to true
							exit repeat
						end if
						if not agentloaded then error "Could not load the launch agent. Make sure that the correct permissions are set on " & POSIX path of (((path to library folder from user domain) as text) & "LaunchAgents")
					end repeat
					
					set end of sleepless to sel
				end repeat
				
				set ASTID to AppleScript's text item delimiters
				set AppleScript's text item delimiters to return
				set sleepless to sleepless as text
				set AppleScript's text item delimiters to ASTID
				
				display dialog "The following drives will be kept awake:" & return & return & sleepless buttons {"More...", "OK"} default button "OK" with icon note with title "Keep Drive Spinning"
				if button returned of result is "OK" then set done to true
			end if
		on error errMsg number errNum
			try
				if errNum is not -128 then
					beep
					display dialog errMsg buttons {"Cancel"} default button "Cancel" with icon stop with title "Keep Drive Spinning"
				end if
			end try
		end try
	else if button returned of result is "Let a drive sleep..." then
		try
			set vols to {}
			try
				set existingAgents to every paragraph of (do shell script "ls ~/Library/LaunchAgents/net.jonstovell.keep*Spinning.plist")
			on error
				display dialog "There are no drives being kept awake." buttons {"Cancel"} default button "Cancel" with icon caution with title "Keep Drive Spinning"
			end try
			repeat with thisAgent in existingAgents
				tell application "System Events" to set vol to value of third property list item of property list item "ProgramArguments" of contents of property list file thisAgent
				set ASTID to AppleScript's text item delimiters
				set AppleScript's text item delimiters to {"[[ -e ", " ]]"}
				set vol to second text item of vol
				set vol to (do shell script "dirname " & vol)
				set vol to (do shell script "basename " & quoted form of vol)
				set AppleScript's text item delimiters to ASTID
				set end of vols to vol
			end repeat
			
			set selected to choose from list vols with prompt "Choose a drive to let sleep." & return & "Press Shift for multiple items." with title "Keep Drive Spinning" with multiple selections allowed
			if selected is false then
				error number -128
			else
				repeat with i from 1 to count selected
					set sel to item 1 of selected
					
					set AppleScript's text item delimiters to space
					set sel_nospace to text items of (sel as text)
					set AppleScript's text item delimiters to ""
					set sel_nospace to sel_nospace as text
					
					-- Unload and delete the launch agent
					do shell script "launchctl unload -w ~/Library/LaunchAgents/net.jonstovell.keep" & quoted form of sel_nospace & "Spinning.plist"
					do shell script "rm -f ~/Library/LaunchAgents/net.jonstovell.keep" & quoted form of sel_nospace & "Spinning.plist"
				end repeat
				display dialog "The following drives will be allowed to sleep:" & return & return & selected buttons {"More...", "OK"} default button "OK" with icon note with title "Keep Drive Spinning"
				if button returned of result is "OK" then set done to true
			end if
		on error errMsg number errNum
			try
				if errNum is not -128 then
					beep
					display dialog errMsg buttons {"Cancel"} default button "Cancel" with icon stop with title "Keep Drive Spinning"
				end if
			end try
		end try
	else
		set done to true
	end if
end repeat
