#!/usr/bin/env ruby

# Don't show warnings, $stdout is being watched by the MTA.
$VERBOSE = nil

# TODO: 
# - make code comments rdoc-compatible.
# - check sanity of listconfig-value like 'myaddr', 'default_mime' etc. 
#   We need them to be properly set to process properly.
# - primary setup-check / is there a valid list-config?/admin?/
#   admin-key?

def usage
  puts "Usage:
#{File.basename($0)} [-c baseconfig] listname < email
#{File.basename($0)} [-c baseconfig] -test [listname]"
  exit 1
end

def process_test(arg)
    usage unless STDIN.tty?
    listname = ARGV.shift
    if listname
      Schleuder.log.debug "Calling Processor.test(#{listname})"
      Schleuder::Processor.test listname
    else
      Schleuder.log.debug "Calling Processor.test"
      Schleuder::Processor.test
    end
end

def process_list(listname)
  usage if STDIN.tty? or ! listname
  Schleuder.log.debug "Running for list #{listname}"
  Schleuder.log.debug 'Reading STDIN'
  # TODO: check for valid IO
  msg = STDIN.read
  Schleuder.log.debug 'Handing over to Processor.run'
  Schleuder::Processor.run listname, msg
end

$:.unshift File.dirname(__FILE__) + '/../lib'
require 'schleuder'
begin 
  arg = ARGV.shift
  if arg == '-c'
    Schleuder.config(ARGV.shift)
    arg = ARGV.shift
  end
  Schleuder.log.debug "I've been called, starting up..."
  case arg
  when '-test'
    process_test(ARGV)
  when /(-h|--help)/
    usage
  when /[A-Za-z0-9]+/
    process_list(arg.gsub(/-(sendkey|bounces|request|owner)(@|$)/, '\2'))
  else
    usage
  end
rescue SystemExit => e
  exit e.status
rescue Errno::EACCES => e
  msg = [e.message, e.backtrace].flatten.join("\n")
  $stderr.puts "File permission error: %s" % msg
  begin
    Schleuder.log.fatal e
  rescue
    begin
      Log4r::Logger['log4r'].error e
    rescue
    end
  end
  exit 1
rescue Exception => e
  begin
    # Log4r mutes all outputters on first exception so if this rescues from a
    # Log4r-error we can't expect the raise of a second exception here.
    # Unfortunately there's no direct way to identify exceptions from Log4r
    # because it throws StandardErrors and we're subclassing.
    callerfile = e.backtrace.first.split(':').first.split('/').last rescue ''
    if e.class == StandardError &&
          ['listlogger.rb', 'schleuderlogger.rb'].include?(callerfile)
      raise e
    else
      Schleuder.log.fatal e
    end
  rescue => f
    msg1 = "Logger exception: #{f}\n#{f.backtrace.join("\n")}"
    msg2 = "...while trying to log this exception: #{e}\n#{f.backtrace.join("\n")}"
    Log4r::Logger['log4r'].error { "#{msg1}\n\n#{msg2}" }
    $stderr.puts(f.message) if $stderr.tty?
  end
  $stderr.puts "A serious error occurred, please notify the administrators of this list or server!"
  exit 1
end
