#!/usr/bin/env ruby -w

if $0 == __FILE__ then
  module Borges; end
  require 'Borges/RequestHandler/RequestHandler'
  require 'Borges/RequestHandler/Dispatcher'

  Borges::Dispatcher.url_prefix = (ARGV.shift || "/cgi-bin/borges")
end

require 'drb'
require 'rinda/ring'

require 'Borges'
require 'Borges/DRb'

class Borges::DRbServer

  include DRbUndumped

  ##
  # Turn a block into a daemon process
  #
  # TODO: Write pid to file

  def self.daemonize
    fork do
      Process.setsid
      fork and exit
      Dir.chdir "/"
      File.umask 0000
      STDIN.reopen "/dev/null"
      STDOUT.reopen "/dev/null", "a"
      STDERR.reopen STDOUT

      yield
    end
  end

  def self.create
    DRb.start_service

    provide_tried = false

    begin
      ::Rinda::RingFinger.new.lookup_ring_any # test for RingServer

    rescue RuntimeError => e
      # HACK: ugly, ugly, make RingNotFound an Exception subclass
      if e.message == 'RingNotFound' and not provide_tried then
        STDERR.puts "Spawning RingServer"

        provide_tried = true
        self.daemonize do
          require 'rinda/tuplespace'

          $0 = 'Borges RingServer'

          DRb.start_service

          Rinda::RingServer.new Rinda::TupleSpace.new

          DRb.thread.join
        end

        sleep 1
        retry
      else
        raise "Unable to start RingServer"
      end
    end

    borges_server = self.new

    service = ::Rinda::RingProvider.new :Borges, borges_server,
                                        "Borges Server"
    service.provide

    return borges_server
  end

  # TODO: on shutdown, unlist service in RingServer

  def self.start
    borges_server = create

    trap('INT') do
      #::Rinda::RingFinger.primary.take [:name, :Borges, borges_server,
      #                                  "Borges Server"]
      DRb.stop_service
    end

    DRb.thread.join
  end

  def initialize
    @handler = Borges::Dispatcher.instance
  end

  def handle_request(request)
    begin
      return @handler.handle_request(request)

    rescue Exception => e
      puts "!!"
      puts e.backtrace.join("\n")
      puts "!!"

      raise e
    end
  end

end # class Borges::DRbServer

if $0 == __FILE__ then
  Borges::DRbServer.start
end

