# Ensure the cron is using the proper version of ruby, and simply run this with:
# ruby mix_cron.rb
#

require 'faraday'
require 'json'
require 'tempfile'

MIXER_EXECUTABLE = "/usr/local/bin/audiomixerapp"
S3CMD = "s3cmd"

# FIXME: This should probably come from an environments file or something
BASE_URL = "http://www.jamkazam.com"

# This must be present on requests from the cron to prevent hackers from
# hitting these routes.
CRON_TOKEN = "2kkl39sjjf3ijdsflje2923j"

AUDIOMIXER_LOG_FILE = "/var/log/audiomixer"

MIX_CRON_WATCH_FILE = "/var/run/mix_cron"


# Don't do anything if the cron is arleady running. There's a theoretical race
# condition here, but it should never actually be a problem because the cron should
# only run every minute or two.
if File.exist?(MIX_CRON_WATCH_FILE)
  psret = `ps axuw | grep mix_cron.rb | grep ruby`
  unless psret.empty?
    puts "Cron still running"
    exit
  end
end

`touch #{MIX_CRON_WATCH_FILE}`


# Get the next manifest to mix
response = Faraday.get "#{BASE_URL}/mixes/next", :token => CRON_TOKEN
if response.status > 299
  puts "Error response getting next mix: #{response.status}, #{response.body}"
  do_exit
end

# This just means no mixes available.
if response.status == 204
  do_exit
end


if response.status != 200
  puts "Unexpected response received: #{response.status}, #{response.body}"
  do_exit
end

json = JSON.parse(response.body)
# This needs to download all the vorbis files, mix and then upload
# the finished one, and tell the server about that.
json['manifest']['files'].map! do |file|
  file['filename'] = Dir::Tmpname.make_tmpname ['/tmp/', '.ogg'], nil 
  file_response = Faraday.get file.url
  if file_response.status != 200
    puts "Error downloading url: #{file.url}"
    do_exit
  end
  File.open(file['filename'], 'wb') { |fp| fp.write(file_response.body) }
end

output_filename = "/tmp/mixout-#{json['id']}.ogg"
IO.popen("#{MIXER_EXECUTABLE} #{output_filename} vorbis >>& #{AUDIOMIXER_LOG_FILE}", "w") do |f|
  f.puts JSON.generate(json)
  f.close
end
 
# First maybe make sure the length is reasonable or something? I bet sox can check that (duration i mean).

# FIXME?: Need to check that the put succeeded before carrying on. Probably can use the exit code or some such.
# Or maybe just do an ls to sanity check it.
`#{S3CMD} -P put #{output_filename} #{json['destination']}`

finish_response = Faraday.put "#{BASE_URL}/mixes/finish", :token => CRON_TOKEN, :id => json['id']
if finish_response.status != 204
  puts "Error calling finish on server for mix_id #{json['id']}: #{finish_response.status}, #{finish_response.body}"
  do_exit
end

puts "Mix complete and uploaded to: #{json['destination']}"
do_exit




def do_exit
  `rm -f #{MIX_CRON_WATCH_FILE}`
end


