from pygame import event, time, key, joystick
from pygame.locals import *
from UserDict import IterableUserDict
from SelfCallMixin import SelfCallMixin

class EventHandler(SelfCallMixin):
	"""
	This singleton keeps track of what events are doing what.
	"""
	def __init__(self):
		self.clock = time.Clock()
		self.evs = []
		self.framerate = 60
		for j in range(joystick.get_count()):
			joystick.Joystick(j).init()

	
	def Pump(self):
		"""
		Pump the events queue.
		"""
		# sleep until we're doing the right fps fps
		self.clock.tick(self.framerate)
		self.evs = event.get()
	
	def GetEvents(self):
		# pump the events queue
		return self.evs

events = EventHandler()

class EventDict(IterableUserDict):
	"""
	A dictionary for holding held keys and an easy way to check if one is held down.
	"""
	def IsHeld(self, key):
		return (self.has_key(key) and self[key])

class EventMonitor(SelfCallMixin):
	"""
	We subclass this guy to monitor what events are being triggered on a class by class basis.
	"""
	def __init__(self):
		self.held = EventDict()
		self.axis = [0, 0, 0, 0, 0, 0]
	
	def Pump(self):
		"""
		The update loop fills everthing and runs the routines needed.
		"""
		for e in events.GetEvents():
			if e.type == QUIT:
				self.CallMethod("Quit")
			elif e.type == KEYDOWN:
				self.CallMethod("KeyDown", e)
				self.CallMethod("KeyDown_" + key.name(e.key), e)
				self.held[e.key] = True
			elif e.type == KEYUP:
				self.CallMethod("KeyUp", e)
				self.CallMethod("KeyUp_" + key.name(e.key), e)
				self.held[e.key] = False
			elif e.type == USEREVENT:
				# music
				self.CallMethod("TuneDone", e)
			elif e.type == MOUSEMOTION:
				self.CallMethod("MouseMove", e)
			elif e.type == MOUSEBUTTONDOWN:
				self.CallMethod("MouseDown", e)
				self.CallMethod("MouseDown_" + str(e.button), e)
			elif e.type == MOUSEBUTTONUP:
				self.CallMethod("MouseUp", e)
				self.CallMethod("MouseUp_" + str(e.button), e)
			elif e.type == JOYAXISMOTION:
				oldval = self.axis[e.axis]
				
				if e.axis in [0, 2, 4]:
					if e.value > 0.5 and oldval < 0.5:
						self.held[K_RIGHT] = True
						self.CallMethod("JoystickDown_right", e)
					elif e.value < 0.5 and oldval > 0.5:
						self.held[K_RIGHT] = False
						self.CallMethod("JoystickUp_right", e)
					elif e.value < -0.5 and oldval > -0.5:
						self.held[K_LEFT] = True
						self.CallMethod("JoystickDown_left", e)
					elif e.value > -0.5 and oldval < -0.5:
						self.held[K_LEFT] = False
						self.CallMethod("JoystickUp_left", e)
				elif e.axis in [1, 3, 5]:
					if e.value > 0.5 and oldval < 0.5:
						self.held[K_DOWN] = True
						self.CallMethod("JoystickDown_down", e)
					elif e.value < 0.5 and oldval > 0.5:
						self.held[K_DOWN] = False
						self.CallMethod("JoystickUp_down", e)
					elif e.value < -0.5 and oldval > -0.5:
						self.held[K_UP] = True
						self.CallMethod("JoystickDown_up", e)
					elif e.value > -0.5 and oldval < -0.5:
						self.held[K_UP] = False
						self.CallMethod("JoystickUp_up", e)
				
				self.axis[e.axis] = e.value
			elif e.type == JOYBUTTONDOWN:
				self.CallMethod("JoyButtonDown", e)
				self.CallMethod("JoyButtonDown_" + str(e.button))
			elif e.type == JOYBUTTONUP:
				self.CallMethod("JoyButtonUp", e)
				self.CallMethod("JoyButtonUp_" + str(e.button))
		
		self.CallMethod("KeysHeld", self.held)
		[self.CallMethod("KeyHeld_" + key.name(s)) for s in self.held if self.held[s]]
	

