#!/opt/mbari/bin/ruby
#Earth Centered Cartesian to Spherical coordinate transform described here:
#  https://microem.ru/files/2012/08/GPS.G1-X-00006.pdf

Epoch = Time.utc(2014,5,11,14,23,55)  #Iridium Epoch

Platform = ARGV[0]
Recipient = ARGV[1] || "mooringtrack"
Sender = ARGV[2] || ENV['USER'] || `hostname`
Server = ARGV[3] || 'mail'
Domain = ARGV[4] || 'mbari.org'

if not Platform or Platform.start_with? '-'
  this=File.basename $0
  STDERR.puts <<END
#{this} emails most recent lat/long coordinates derived from IridiumLocation
entries in Linux system log to #{Recipient}@#{Domain} -- brent@mbari.org 2/27/20
Output time in epoch seconds associated with this update
First argument is the ODSS platform name
Optional 2nd argument is the recipient   [#{Recipient}]
Optional 3rd argument is the sender      [#{Sender}]
Optional 4th argument is the smtp server [#{Server}]
Optional 5th argument is the domain name [#{Domain}]
Suppress all emails if recipient == '-'
Environment:
  Suppress email while lastUpdate <= Iridium time of last update already emailed
Output:
  stdout:  the hexadecimal Iridium time of the most recent update emailed
  stderr:  the text of all updates emailed
Example:
  curl -s ftp://espshore/moe/esp/messages | #{this} GoMex20
END
  exit 2
end

include Math
DegPerRad = 180/PI
A = 6378.137
B = 6356.7523142451
b2 = B*B
a2 = A*A
a2lessB2 = a2 - b2
E2 = a2lessB2 / a2
Eprime2 = a2lessB2 / b2

def update match, frame=match[4].hex
  epochSecs = Epoch + 0.09*frame
  x,y,z = Integer(match[1]), Integer(match[2]), Integer(match[3])
  p = sqrt(x*x + y*y)
  theta = atan2 A*z, p*B
  lat = atan2(z + Eprime2*B*sin(theta)**3, p - E2*A*cos(theta)**3) * DegPerRad
  long = atan2(y,x) * DegPerRad
  location='%.3f,%.3f' % [long,lat]
  subject = "#{Platform},#{epochSecs.to_i},#{location}"
  STDERR.puts subject
  return if Recipient == '-'

  msgstr = <<-END
Subject: #{subject}
Date: #{`date -R`}

#{subject}
  END

  require 'net/smtp'
  Net::SMTP.start(Server, 25, Domain) do |smtp|
    smtp.send_message msgstr, Sender, "#{Recipient}@#{Domain}"
  end
end

loc = /\s+IridiumLocation:\s*(-?\d+),(-?\d+),(-?\d+),([0-9a-f]+)/i
match = frame = nil
lastUpdate = ENV['lastUpdate']
lastUpdate &&= lastUpdate.hex
STDIN.each do |logLine|
  next unless match = loc.match(logLine)
  frame = match[4].hex
  raise "Invalid timestamp: #{match[4]}" if frame == 0
  update match, frame if lastUpdate and frame > lastUpdate
end
raise "No IridiumLocation log entries found" unless match
update match, frame unless lastUpdate
puts "0x%x" % frame