class GameController(object):
	"""
	The main game class.  
	
	This handles all game related code including setting up the scene, displaying user
	interfaces, managing sound, etc etc.
	"""
	def __init__(self, application, engine, settings):
		self._application = application
		self._engine = engine
		self._settings = settings
		
		self._soundmanager = engine.getSoundManager()
		self._soundmanager.init()
		
		self._keystate = KeyState()
		
		self._guicontroller = GUIController(self)
		
		self._listener = GameListener(self)
		
		self._guicontroller.showMainMenu()
		
		self._questmanager = QuestManager(self)
		
		self._scene = None
		self._instancerenderer = None
		self._floatingtextrenderer = None
		
		self._switchmaprequested = False
		self._newmap = None
		
	def onConsoleCommand(self, command):
		"""
		Parses game related console commands.
		"""
		
		result = ""
		
		args = command.split(" ")
		cmd = []
		for arg in args:
			arg = arg.strip()
			if arg != "":
				cmd.append(arg)
		
		if cmd[0] == "spawn":
			result = "Usage: spawn [object template] [posx] [posy] "
			if len(cmd) != 4:
				return result
			else:
				try:
					id = str(uuid.uuid1())
					valdict = { "posx" : float(cmd[2]), "posy" : float(cmd[3]) }
					obj = self._scene.loadObject(cmd[1], id, valdict)
				except ObjectNotFoundError as e:
					result = "Error: Cannot load [" + cmd[1] + "].  It could not be found!"
					obj = None
					
				if obj:
					try:
						self._scene.addObjectToScene(obj)
						obj.position = (float(cmd[2]), float(cmd[3]))
						result = "--OK--"
					except ObjectAlreadyInSceneError as e:
						result = "Error: [" + cmd[1] + "] is already on the scene."
						
		elif cmd[0] == "move":
			result = "Usage: move [object id] [posx] [posy]"
			if len(cmd) != 4:
				return result
			else:
				obj = self._scene.getObject(cmd[1])
				if obj:
					obj.position = (float(cmd[2]), float(cmd[3]))
					result = "--OK--"
				else:
					result = "Error: [" + cmd[1] + "] does not exist on the scene."
					
		elif cmd[0] == "loadmap":
			result = "Usage: loadmap [map name]"
			
			
		return result
		
	def newGame(self):
		"""
		Removes any save games and starts a new game.
		"""
		
		self._guicontroller.hideMainMenu()
		
		for filename in glob.glob(os.path.join("saves" , "*.xml")):
			os.remove(filename)
		
		
		self._questmanager.reset()
		self._questmanager.deserialize()
		
		mapname = self._settings.get("RPG", "TownMapFile", "town")
		self.loadMap(mapname)
		
		
	def loadMap(self, mapname):
		"""
		Creates the scene for the map and attaches the listener.		
		"""
	
		if self._listener:
			self._listener.detach()
		
		self._keystate.reset()
		
		if self._scene:
			self._scene.destroyScene()
			self._scene = None
		
		self._scene = Scene(self)
		
		self._scene.createScene(mapname)
		
		self._instancerenderer = fife.InstanceRenderer.getInstance(self._scene.cameras[self._settings.get("RPG", "DefaultCameraName", "camera1")])
		self._floatingtextrenderer = fife.FloatingTextRenderer.getInstance(self._scene.cameras[self._settings.get("RPG", "DefaultCameraName", "camera1")])
		self._floatingtextrenderer.addActiveLayer(self._scene.actorlayer)
		font = get_manager().getDefaultFont()
		self._floatingtextrenderer.setFont(font)
		self._floatingtextrenderer.setBackground(255, 100, 100, 165) 
		self._floatingtextrenderer.setBorder(255, 50, 50)
		self._floatingtextrenderer.setEnabled(True)
		
		if self._listener:
			self._listener.attach()

	def switchMap(self, newmapname):
		"""
		Queues a map switch for next frame.  This must be done next frame to ensure
		all events pertaining to the current frame have finished being processed.
		"""
		self._switchmaprequested = True
		self._newmap = newmapname
		
		#save before switching scenes
		self._scene.serialize()
	
	def endGame(self):
		"""
		Saves the game state and destroys the scene.
		"""
		if self._scene:
			self._scene.serialize()
			
			self._listener.detach()
			self._scene.destroyScene()
			self._questmanager.reset()
			
			self._scene = None
			self._instancerenderer = None
			self._floatingtextrenderer = None
		
	def quit(self):
		self.endGame()
		self._application.requestQuit()

	def pump(self):
		if self._switchmaprequested:
			self.loadMap(self._newmap)
			self._newmap = None
			self._switchmaprequested = False
	
		if self._scene:
			self._scene.updateScene()
		
		
	def _getGUIController(self):
		return self._guicontroller
		
	def _getQuestManager(self):
			return self._questmanager
	
	def _getEngine(self):
		return self._engine
		
	def _getSettings(self):
		return self._settings
		
	def _getScene(self):
		return self._scene
	
	def _getKeyState(self):
		return self._keystate
	
	def _getInstanceRenderer(self):
		return self._instancerenderer
		
	def _getLogManager(self):
		return self._application.logger
	
	guicontroller = property(_getGUIController) 
	questmanager = property(_getQuestManager)
	engine = property(_getEngine)
	settings = property(_getSettings)
	scene = property(_getScene)
	keystate = property(_getKeyState)
	instancerenderer = property(_getInstanceRenderer)
	logger = property(_getLogManager)