require 'thread'

module RubyMud

# Anything that wants to be able to tick
# should include this (Look at TickObject)
# Note: This is a module not a class
module Tickable
	# This is called by the tick queue
	# when the object ticks
	def tick()
	end	
end

# This is for the main ticking objects
# Eg. the main ticking object ticks 
# every 60(or whatever) seconds. Other
# Tickable object then connect to these
class TickObject

	# The time this tick object should run
	attr_accessor :time
	# Object this tick is associated with
	attr_accessor :object

	# Object could be nil
	def initialize(object,time)
		@time = time
		@object = object
		TickQueue.add(self)
	end
	
end

# This is the tick queue
# You can place TickObject on this queue
class TickQueue
	private_class_method :new

	@@tickObjects = PQueue.new(proc{|x,y| x.time<y.time})
	
	# Starts a thread that currently only ticks 
	# once a second I guess we need to implement 
	# a self blocking system
	def TickQueue.setup()
		@mutex = Mutex.new
		Thread.start do
			begin
				
				loop do
					sleep 1
					TickQueue.tick()
				end
			
			rescue => detail
		
				print "\n\n ---------\n !!!ERROR!!!\n"
				print $!
				print detail.backtrace.join("\n")
				print "---------\n\n"			
			end
		end
	end
	
	# Add a tick object to the queue
	def TickQueue.add(tickObject)
		@mutex.synchronize do
			@@tickObjects.push(tickObject)
		end
	end
	
	def TickQueue.clear()
		@@tickObjects.clear
	end
	
	def TickQueue.getQueue
		@@tickObjects
	end	
	
	def TickQueue.tick()
		
		if (@@tickObjects.size == 0)
			return
		end
				
		now = Time.now
		
		# Execute all the TickObjects that have a time less than now
		first = @@tickObjects.top
		while (first.time < now)
			#print "\n"+@@tickObjects.size.to_s()+"\n"
			@@tickObjects.pop
			#print "\n"+@@tickObjects.size.to_s()+"\n"
			first.object.tick()
			first = @@tickObjects.top
			if (first == nil)
				return
			end			
		end
	end
	
end

end #module