import bge
from random import randint
from time import clock
   
   
#====================================
class Transition(object):
	def __init__(self, toState):
		self.toState = toState
	def Execute(self):
		#print('Transitioning ...', self.toState)
		pass
			
   
   
#====================================
State = type("State", (object,), {})

class State(object):
	def __init__(self, FSM):
		self.FSM = FSM
		self.timer = 0
		self.startTime = 0
	def Enter(self):
		pass
		#print('entering')
	def Execute(self):
		pass
		#print('Executing')
	def Exit(self):
		pass
		#print('Exiting')
		
class Target1(State):
	def __init__(self,FSM):
		super(Target1, self).__init__(FSM)    
		
	def Enter(self):
		#print('Preparing to walk towards target 1.')
		self.cont = bge.logic.getCurrentController()
		self.FSM.stateLife = 1
		self.own = self.cont.owner
		self.target = 'larryTarget'
		self.npcArm = self.own.children['npc']
		self.scene = bge.logic.getCurrentScene()
		self.actu = self.cont.actuators['Steering']

		nm = self.own['navMesh']
		pt = nm.findPath(self.own.worldPosition, self.scene.objects[self.target].worldPosition)
		print('path is', pt)		

		if 'larryTarget' in self.scene.objects:
				self.actu.target = self.target			
				self.actu.velocity = 1.5
				self.actu.turnspeed = 20
				self.actu.facingMode = False
				self.actu.navmesh = self.own['navMesh']
				self.cont.activate(self.actu)

		super(Target1, self).Enter()
		
	def Execute(self):
		#print('Tracking target 1.', self.FSM.stateLife)
		self.FSM.stateLife += 1
		duration = 500
		if self.FSM.stateLife > duration:
			num = randint(1,2)
			if num == 1:
				self.FSM.ToTransition('toTarget2')
			elif num ==2:
				self.FSM.ToTransition('toTarget3')	
			else:
				self.FSM.ToTransition('toIdle')
		else:	
			self.cont.activate(self.actu)	
			self.npcArm.playAction('g_walk2', 1,62, layer=2, play_mode=0, speed=.5)			
			
	def Exit(self):
		#print('Finished target 1') 
		self.cont.deactivate(self.actu) 

class Target2(State):
	def __init__(self,FSM):
		super(Target2, self).__init__(FSM)    
		
	def Enter(self):
		#print('Preparing to walk towards target 2.')
		self.cont = bge.logic.getCurrentController()
		self.FSM.stateLife = 1
		self.own = self.cont.owner
		self.target = 'larryTarget.001'
		self.npcArm = self.own.children['npc']
		self.scene = bge.logic.getCurrentScene()
		self.actu = self.cont.actuators['Steering']

		if 'larryTarget.001' in self.scene.objects:
				self.actu.target = self.target			
				#self.actu.velocity = 1.5
				#self.actu.turnspeed = 20
				#self.actu.facingMode = False
				#self.actu.navmesh = self.own['navMesh']
				#self.cont.activate(self.actu)

		super(Target2, self).Enter()
		
	def Execute(self):
		#print('Tracking target 2.', self.FSM.stateLife)
		self.FSM.stateLife += 1
		duration = 1000
		if self.FSM.stateLife > duration:
			num = randint(1,3)
			if num == 1:
				self.FSM.ToTransition('toTarget1')
			elif num ==2:
				self.FSM.ToTransition('toTarget3')	
			else:
				self.FSM.ToTransition('toIdle')
		else:		
			self.cont.activate(self.actu)
			self.npcArm.playAction('g_walk2', 1,62, layer=2, play_mode=0, speed=.5)			
							
				
	def Exit(self):
		#print('Finished target 2') 
		self.cont.deactivate(self.actu)          
		
class Target3(State):
	def __init__(self,FSM):
		super(Target3, self).__init__(FSM)    
		
	def Enter(self):
		#print('Preparing to walk towards target 3.')
		self.cont = bge.logic.getCurrentController()
		self.FSM.stateLife = 1
		self.own = self.cont.owner
		self.target = 'larryTarget.002'
		self.npcArm = self.own.children['npc']
		self.scene = bge.logic.getCurrentScene()
		self.actu = self.cont.actuators['Steering']

		if 'larryTarget.002' in self.scene.objects:
				self.actu.target = self.target			
				#self.actu.velocity = 1.5
				#self.actu.turnspeed = 20
				#self.actu.facingMode = False
				#self.actu.navmesh = self.own['navMesh']
				self.cont.activate(self.actu)
		super(Target3, self).Enter()

		
	def Execute(self):
		self.FSM.stateLife += 1
		duration = 1200
		if self.FSM.stateLife > duration:
			if not (randint(1,3) % 2):
				self.FSM.ToTransition('toTarget1')
			else:
				self.FSM.ToTransition('toTarget2')
		else:
			cont = bge.logic.getCurrentController()
			own = cont.owner
			npcArm = own.children['npc']
			npcArm.playAction('g_walk2', 1,62, layer=2, play_mode=0, speed=.5)		
			

	def Exit(self):
		#print('Finished target 3') 
		self.cont.deactivate(self.actu)              
		
		
class Idle(State):
	
	def __init__(self,FSM):
		super(Idle, self).__init__(FSM)  
		
	def Enter(self):
		#print('Starting to idle.')
		self.cont = bge.logic.getCurrentController()
		self.own = self.cont.owner
		self.npcArm = self.own.children['npc']
		self.FSM.stateLife = 1

		super(Idle, self).Enter()
		
	def Execute(self):
		#print('Idleing.', self.FSM.stateLife)
		self.FSM.stateLife += 1
		duration = 300
		if self.FSM.stateLife > duration:
			#num = randint(1,4)
			self.FSM.ToTransition('toTarget1')
			# if num == 1:
			# 	self.FSM.ToTransition('toTarget1')
			# elif num == 2:
			# 	self.FSM.ToTransition('toTarget2')	
			# elif num == 3:
			# 	self.FSM.ToTransition('toTarget3')
			# elif num == 4 or num == 5 or num == 6:
			# 	self.FSM.ToTransition('toImpatient')										
			# else:
			# 	self.FSM.ToTransition('toIdle')
		else:
			#pass
			#print(self.own.children)
			self.npcArm.playAction('g_idle', 1,201, layer=2, play_mode=0, speed=.5)	
			
	def Exit(self):
		pass
		##print('Waking up from idle.') 


class Startup(State):
	
	def __init__(self,FSM):
		super(Startup, self).__init__(FSM)  
		
	def Enter(self):
		self.FSM.stateLife = 1
		super(Startup, self).Enter()
		
	def Execute(self):
		self.FSM.stateLife += 1
		duration = 4
		if self.FSM.stateLife > duration:
				self.FSM.ToTransition('toIdle')
			
	def Exit(self):
		#pass
		print('Exiting npc startup.') 		

class Impatient(State):
	
	def __init__(self,FSM):
		super(Impatient, self).__init__(FSM)  
		
	def Enter(self):
		#print('Starting to idle.')
		self.FSM.stateLife = 1
		self.cont = bge.logic.getCurrentController()
		self.own = self.cont.owner
		self.npcArm = self.own.children['npc']	
		super(Impatient, self).Enter()
		
	def Execute(self):
		##print('being Impatient.', self.FSM.stateLife)
		self.FSM.stateLife += 1
		duration = 300
		if self.FSM.stateLife > duration:
			self.FSM.ToTransition('toIdle')
		else:
			pass
			#self.npcArm.playAction('npcImpatient', 1,201, layer=2, play_mode=0, speed=.5)	
			
	def Exit(self):
		pass
		#print('stopping bening impatient.') 		         
						   
					 
#===================================
						

class FSM(object):
	def __init__ (self, character):
		self.char = character
		self.states = {}
		self.transitions = {}
		self.curState = None
		self.prevState = None
		self.trans = None
		self.stateLife = 0
		
	def AddTransition(self, transName, transition):
		self.transitions[transName] = transition
	
	def AddState(self, stateName, state):
		self.states[stateName] = state        
		
	def SetState(self, stateName):
		self.prevState = self.curState
		self.curState = self.states[stateName]
		
	def ToTransition(self, toTrans):
		self.trans = self.transitions[toTrans]
		
	def Execute(self):
		if (self.trans):
			self.curState.Exit()
			self.trans.Execute()
			self.SetState(self.trans.toState)
			self.curState.Enter()
			self.trans = None        
		self.curState.Execute()    
				
#====================================
Char = type("Char",(object,),{})

class Walker(Char):
	def __init__(self):
		self.FSM = FSM(self)
		#cont = bge.logic.getCurrentController()
		#own = cont.owner
		#self.LightOn = own['state']
		
		##STATES
		self.FSM.AddState("Startup", Startup(self.FSM))
		self.FSM.AddState("Idle", Idle(self.FSM))
		self.FSM.AddState("Impatient", Impatient(self.FSM))
		self.FSM.AddState('Target1', Target1(self.FSM))
		self.FSM.AddState('Target3', Target3(self.FSM))
		self.FSM.AddState('Target2', Target2(self.FSM))
		
		#TRANSITIONS
		self.FSM.AddTransition('toStartup', Transition('Startup'))
		self.FSM.AddTransition('toIdle', Transition('Idle'))
		self.FSM.AddTransition('toImpatient', Transition('Impatient'))
		self.FSM.AddTransition('toTarget3', Transition('Target3'))
		self.FSM.AddTransition('toTarget1', Transition('Target1'))
		self.FSM.AddTransition('toTarget2', Transition('Target2'))
		
		
		if self.FSM.curState == None:
			self.FSM.SetState('Startup')
			#self.FSM.ToTransition('toIdle')
			#print('setting none')
	
	def Execute(self):
		self.FSM.Execute()    
#====================================     
r = Walker()
def main(cont):
	own = cont.owner   
	scene = bge.logic.getCurrentScene()
	if 'inited' not in own:
		own['inited'] = True
		own['frame'] = 0
		own['state'] = 'On'
		own['navMesh'] = None

		for x in scene.objects:
			if 'npcNavmesh' in x:
				own['navMesh'] = x
		#print('initing')

	if own['frame'] == 40:
		own.worldPosition = [0,0,50]	

		ln = own['cName'] + '_loader'
		if ln in scene.objects:
			to = scene.objects[ln]	
			own.worldPosition = to.worldPosition
			#own.worldPosition.z += 50


	#r.Execute()    
	##print(r.FSM.curState)


	own['frame'] += 1
	yvel = own.linearVelocity.y
	yvel = yvel *.05
	if own.linearVelocity.y > .01 or own.linearVelocity.y < -.01:
		own.applyRotation([0,0,yvel], True)		