require 'rubygems'
require 'thread'
require 'singleton'
require 'webrick'

DEFAULT_PORT = 19000

# Mimic Win32 event - allows thread guarded by mutex to wait for signal before resuming.
class Event < ConditionVariable
    def initialize(isManualReset = true, name = "")
        @isManualReset = isManualReset
        @state = :nonsignaled
        @name = name
        super()
    end

    attr_reader :name
    attr_reader :isSet

    def wait(mutex)
        @waiterThread = Thread.new \
        {
            mutex.synchronize\
            {
                if (:signaled != @state)
                else
                    super(mutex)
                end
                if (!@isManualReset)
                    @state = :nonsignaled
                end
            }
        }

        # Blocks the current thread until the waiter is woken by a signal.
        @waiterThread.join()
    end

    def signal(mutex)
        super()
        mutex.synchronize\
        {
            @state = :signaled
        }
    end

    def reset(mutex)
        mutex.synchronize\
        {
            @state = :nonsignaled
        }
    end
end

class Service
    # @Theoretically we should only have one service instance for each test process.
    include Singleton

    def initialize()
        @isRunning = false
        @mutex = Mutex.new
        @serverStartEvent = Event.new(true, "startEvent")
    end

    attr_reader :httpServer
    attr_accessor :isRunning

    def wakeThreadCallback()
        @config[:StartEvent].signal(@mutex)
        Thread.pass()
    end

    def start(httpPort = DEFAULT_PORT)
        if (false == @isRunning)
            @isRunning = true
            @config = {:Port => httpPort, :StartCallback => Proc.new{wakeThreadCallback}, :StartEvent => @serverStartEvent, :Mutex => @mutex}
            @httpServer = WEBrick::HTTPServer.new(@config)

            # Start the HTTP server in a separate thread (otherwise it blocks) to let it
            # process HTTP requests in the background while the test continues to execute.
            @httpServerThread = Thread.new \
            {
                Thread.pass()
                @httpServer.start()
            }

            @serverStartEvent.wait(@mutex)
            @serverStartEvent.reset(@mutex)
        else
        end
    end

    def stop()
        @httpServer.shutdown()
        @httpServerThread.join()
        @isRunning = false
    end
end

@service = Service.instance()
@service.start()
@service.stop()
