#!/usr/bin/ruby
#
# Make an image file list in the format
# required by MB-System
#
# Assumes that this script is run from the
# 'usual' perls/bin directory.
#
# Defaults to the survey directory linked to
# by perls/bin/latest. Otherwise, uses the first
# argument as the survey directory.
#

require 'parsedate'

##
# Usage.
#
def usage
  puts("Usage: make_imagelist.rb survey_dir timestamp_delta")
  puts("\tsurvey_image_dir - path to survey directory (latest)")
  puts("\ttimestamp_delta  - file timestamp delta that defines a match (0.5)")
end

##
# Return the epoch-time representation of timestamp embedded
# in the filename.
# Example: "rIMG-20111010-162021-892347-2.tif"
#
def to_epoch(filename)
  # Extract the timestamp from the right image name
  #
  fl = filename.split("-")    # time components separated by "-"
  date = fl[1]                # date is the 2nd item
  time = fl[2]                # time is the 3rd
  mic  = fl[3].to_f/1000000.0 # Microseconds is the 4th item.

  # Use ParseDate to extract date and time
  # then get the equivalent local time
  #
  res = ParseDate.parsedate(date+time)
  timestamp = Time.local(*res)

  return timestamp.to_f + mic
end

##
# Find filename in dir_array the matches fname
# Assumes specific filename formats.
# Return both the matched filename and the
# timestamp difference. Otherwise nil.
#
def find_match(fname, dir_array, delta)
  dir_array.each { |d|
    # Within a tenth of a second? We got a match.
    #
    if ( (diff = to_epoch(d) - to_epoch(fname)).abs < delta )
      return d, diff
    end
  }
  return nil, nil
end

##
# Writes the filenames to the file along with
# the corresponding timestamp embedded in the
# right image filename.
# Example: "lIMG-20111010-162021-892347-2.tif"
#  Oct 10, 2011 at 16:20:21 and 892 milliseconds
#
def write_match(file, lname, rname, diff)
  timestamp = "%.3f" % to_epoch(lname)
  d = "%.6f" % diff
  file.write("left/#{lname}\t\tright/#{rname}\t\t#{timestamp}\t#{d}\n")
end



##
# Go to the image directory and ensure that subdirectories exist
#
if (ARGV.length > 0)
  wd = ARGV[0]
else
  wd = "latest"  # Default directory
end
wd += "/images"

right_dir = wd + "/right"
left_dir = wd + "/left"
begin
  raise "No 'images' directory" unless (File.directory?(wd))
  raise "No \'left\' directory" unless (File.directory?(left_dir))
  raise "No \'right\' directory" unless (File.directory?(right_dir))
rescue Exception => e
  puts("Cannot find image directories at #{wd}: #{e}")
  usage()
  exit
end
puts("Generating imagelist.mb-2 in #{wd} ...")

if (ARGV.length > 1)
  delta = ARGV[1].to_f
else
  delta = 0.5
end

##
# Open the image list files
#
Dir.chdir(wd)
list_file = File.new("imagelist.mb-2", "w")
rejects = File.new("no_match.txt", "w")

##
# Get the directory listings
#
Dir.chdir("right")
right_list = Dir.glob("*.tif").sort
Dir.chdir("../left")
left_list  = Dir.glob("*.tif").sort

##
# Populate the matched image list file
# and the reject file.
#
n = 0
right_list.each { |rt|

  # Try to find a timestamp match in the left camera list
  # to the file from the right camera list.
  #
  lt, diff = find_match(rt, left_list, delta)

  # Write the filenames if a match is found
  #
  if (lt) 
    write_match(list_file, lt, rt, diff)
    left_list.delete(lt)      # Make the domain list shorter
    n += 1; print("\r#{n}\r"); STDOUT.flush
  else
    rejects.write("#{rt}\n")  # Track the rejects
  end
}

# Finish the reject file. Any file left in the
# left camera list was not matched.
#
left_list.each { |lt|
  rejects.write("#{lt}\n")
}
list_file.close
rejects.close

# Final stats
#
puts("#{n} of #{right_list.length} image matches within #{delta} seconds.")
