#!/usr/bin/ruby.ruby2.4 

require 'pushover'

include Bini
include Pushover
Options.on("-u", "--user USER", "Which user, can be a saved name or token.") { |o| Options[:user] = o}
Options.on("-a", "--app APPKEY", "Which app to notify, can be a saved name or apikey.") { |o| Options[:token] = o}
Options.on("-t", "--title [TITLE]", "Set the title of the notification (optional).") { |o| Options[:title] = o}
Options.on("-p", "--priority [PRIORITY]", "Set the priority of the notification from (low,normal,high,emergency) (optional).") { |o| Options[:priority] = o}
Options.on("-d", "--device [DEVICE]", "Specify the device to send the notifcation to. (optional).") { |o| Options[:device] = o}
Options.on("-c", "--config_file [FILE]", "Set the target config file.") {|o| Options[:config_file] = o}
Options.on("--url [URL]", "Supplementary URL") { |o| Options[:url] = o }
Options.on("--url_title [TITLE]", "Supplementary URL title.") { |o| Options[:url_title] = o }
Options.on("--time [TIME]", "Set the messages time.") {|o| Options[:timestamp] = o}
Options.on("--save-app NAME", "Saves the application to the config file under NAME.") { |o| Options[:save_app] = o}
Options.on("--save-user NAME", "Saves the user to the config file under NAME.") { |o| Options[:save_user] = o}
Options.on("--sound [SOUND]", "Specify the sound to use.  Can be a partial string as long as it is unambiguous enough.") { |o| Options[:sound] = o}
Options.on("--sound_list", "Display the current list of available sounds.  Requires an app token.") { |o| Options[:sound_list] = true}
Options.on("--emergency_retry [TIME]", "The time in seconds between retries.") { |o| Options[:retry] = o}
Options.on("--emergency_expire [TIME]", "How long the emergency notification will hang around.") { |o| Options[:expire] = o}
Options.on("--emergency_callback_url [URL]", "A callback url to use when the notification is acknowledged.") { |o| Options[:callback] = o}
Options.on("--receipts", "List the receipts cached and if they have been acknowledged or not.") {|o| Options[:receipts] = true}

Options.parse!
bail = false

# Order is important.
if Options[:config_file]
	Bini::Config.options[:file] = Options[:config_file]
	puts "Selected config file: #{Options[:config_file]}"
	# TODO: Make a healper for changing config so it clears/loads automatically.
	Bini::Config.clear
	Bini::Config.load
end

if Options[:save_app]
	App.add Options[:save_app], Options[:token]
	puts "Saved application #{Options[:token]} to #{Options[:save_app]}."
	bail = true
end

if Options[:save_user]
	User.add Options[:save_user], Options[:user]
	puts "Saved user #{Options[:user]} to #{Options[:save_user]}."
	bail = true
end

exit if bail # We don't care if we have a message, we should exit here.

if !App.current_app?
	puts "Couldn't find an app via the cli or save file."
	bail = true
end

if !User.current_user?
	puts "Couldn't find a user via the cli or save file."
	bail = true
end

if Options[:sound_list]
	puts "Current Sound List:"
	if Pushover.sounds
		Pushover.sounds.each { |k,v| puts "  #{v}" }
	else
		puts "Error retrieving sound list, are you connected to the internet?  are your credentials correct?"
		exit
	end
	bail = true
end

if Options[:receipts]
	puts 'Updating receipts'
	Pushover::Priority.update_receipts
	Pushover::Priority::Receipts.each do |k,v|
		if v["acknowledged"] != 0
			print "Receipt #{k} was acknowledged at #{Time.at v["acknowledged_at"]}, "
		else
			print "Receipt #{k} has not been acknowledged yet, "
		end

		if v["expired"] == 0
			puts "and will expire at: #{Time.at v["expires_at"]}."
		else
			puts "and expired at: #{Time.at v["expires_at"]}."
		end
	end
	exit
end

if Options[:sound]
	sounds = Pushover.sounds
	if !sounds
		puts "Error retrieving sound list, are you connected to the internet?  are your credentials correct?"
		exit
	end
	match = sounds.select { |k,v| v.downcase.start_with? Options[:sound].downcase}
	if !match || match.count == 0
		puts "No such sound: #{Options[:sound]}."
		bail = true
	elsif match.count > 1
		print "Sound is ambiguous, possible matches: "
		match.each {|k,v| print "#{v} "}
		print "\n"
		bail = true
	else
		Options[:sound] = match.first[0]
	end
end

if Options[:priority]
	# Is this an emergency, did we include everything we need?
	if Priority.is_emergency?(Options[:priority])
		Options[:retry] = 30 if !Options[:retry]
		Options[:expire] = 86400 if !Options[:expire]
	end
end

exit if bail

message = ARGV.join(" ")
if !message
	puts "Must supply a message to be sent."
	bail = true
end

exit if bail

options = Options[].select { |k,v| v}
options[:token] = Pushover::App.current_app
options[:user] = Pushover::User.current_user

options.delete :config_file
options.merge! message:message

response = Pushover.notification options
if response.code == 500
	puts "Something is broken at pushover.net and it is returning 500's (server errors).  Here is the response body."
	puts response.body
	exit
end
j = Yajl.load response.body

if response.code == 200
	if Priority.is_emergency?(Options[:priority])
		j = Yajl.load response.body
		Pushover::Priority.process_receipt j["receipt"]
		puts "emergency notification receipt: #{j["receipt"]}"
	end
	puts "Message sent successfully!"
else
	puts "ErrorCode (#{response.code}): #{j['errors'].first}."
end

