import bge
from random import randint
import actionsFSMlist

MAIN_LAYER = 10
TRANS_LAYER = 12

def getOwn():
	cont = bge.logic.getCurrentController()
	own = cont.owner
	return own

def transPlaying():
	scene = bge.logic.getCurrentScene()
	skater = scene.objects['Char4']
	if skater.isPlayingAction(TRANS_LAYER):
		return True
	else:
		return False	

def stopTrans():
	scene = bge.logic.getCurrentScene()
	skater = scene.objects['Char4']
	if skater.isPlayingAction(TRANS_LAYER):
		skater.stopAction(TRANS_LAYER)	

def getCurFrame():
	scene = bge.logic.getCurrentScene()
	skater = scene.objects['Char4']
	if skater.isPlayingAction(TRANS_LAYER):
		num = round(skater.getActionFrame(TRANS_LAYER), 3)
		print('playing frame ', num)
		return num
	else:
		return None	

def interupt_request():
	cont = bge.logic.getCurrentController()
	own = cont.owner
	print(own['requestAction'])
	if own['requestAction'] in actionsFSMlist.reg_fliplist or own['requestAction'] in actionsFSMlist.fak_fliplist:
		print('flip is true')
		return True
		
	else:
		return False						

def actionPlayer(ac, FSM):
	scene = bge.logic.getCurrentScene()
	skater = scene.objects['Char4']
	deck = scene.objects['deck']
	trucks = scene.objects['trucks']
	name = ac.FSM.action.s_action
	start = ac.FSM.action.s_se[0]
	end = ac.FSM.action.s_se[1]
	layer = ac.FSM.action.layer
	mode = ac.FSM.action.mode
	speed = ac.FSM.action.speed
	
	skater.playAction(name, start,end, layer=layer, play_mode=mode, speed=speed)
	
def transEndPlayer(ac, FSM):

	scene = bge.logic.getCurrentScene()
	skater = scene.objects['Char4']
	deck = scene.objects['deck']
	trucks = scene.objects['trucks']
	name = ac.FSM.action.s_action
	end = ac.FSM.action.s_se[1]
	
	skater.playAction(name, end,end, layer=TRANS_LAYER, play_mode=1, speed=1)	

#====================================
class Transition(object):
	def __init__(self, toState):
		self.toState = toState
	def Execute(self):
		print('Transitioning ...', self.toState)

#====================================   
#====================================
#====================================   
#====================================
#====================================   
#====================================

State = type("State", (object,), {})

class State(object):
	def __init__(self, FSM):
		self.FSM = FSM
		self.timer = 0
		self.startTime = 0

	def Enter(self):
		self.timer = randint(0,5)
		self.startTime = 0
	def Execute(self):
		print('Executing')
	def Exit(self):
		print('Exiting')

#====================================
#====================================		
		
class reg_roll(State):
	def __init__(self,FSM):
		super(reg_roll, self).__init__(FSM) 
		
	def Enter(self):
		print('entering: ', type(self).__name__)
		self.FSM.action = getattr(actionsFSMlist, type(self).__name__) 
		super(reg_roll, self).Enter()
		
	def Execute(self):
		print('executing: ', type(self).__name__)
		self.FSM.stateLife += 1
		actionPlayer(self, FSM)
		own = getOwn()
		if own['requestAction'] == 'reg_opos':
			self.FSM.ToTransition('toreg_roll_to_opos') 
		if own['requestAction'] == 'reg_turnLeft':
			self.FSM.ToTransition('toreg_roll_to_left') 			  

	def Exit(self):
		print('exiting: ', type(self).__name__)


class reg_opos(State):
	def __init__(self,FSM):
		super(reg_opos, self).__init__(FSM)    
		
	def Enter(self):
		print('entering: ', type(self).__name__)
		self.FSM.action = getattr(actionsFSMlist, type(self).__name__) 
		super(reg_opos, self).Enter()
		
	def Execute(self):
		print('executing: ', type(self).__name__)
		self.FSM.stateLife += 1
		dict = bge.logic.globalDict
		actionPlayer(self, FSM)
		own = getOwn()
		if own['requestAction'] != 'reg_opos':      
			self.FSM.ToTransition(self.FSM.action.parentTrans)
	def Exit(self):
		print('exiting: ', type(self).__name__)

class reg_left(State):
	def __init__(self,FSM):
		super(reg_left, self).__init__(FSM)    
		
	def Enter(self):
		print('entering: ', type(self).__name__)
		self.FSM.action = getattr(actionsFSMlist, type(self).__name__) 
		super(reg_left, self).Enter()
		
	def Execute(self):
		print('executing: ', type(self).__name__)
		self.FSM.stateLife += 1
		actionPlayer(self, FSM)
		own = getOwn()
		if own['requestAction'] != self.FSM.action.requestAction:	
			self.FSM.ToTransition(self.FSM.action.parentTrans) 
			print('initing left')       
	
	def Exit(self):
		print('exiting: ', type(self).__name__)	
	
#====================================
#====================================

class reg_roll_to_opos(State):
	def __init__(self,FSM):
		super(reg_roll_to_opos, self).__init__(FSM)    
		
	def Enter(self):
		print('entering: ', type(self).__name__)
		self.FSM.action = getattr(actionsFSMlist, type(self).__name__) 
		super(reg_roll_to_opos, self).Enter()
		
	def Execute(self):
		print('executing: ', type(self).__name__)
		dict = bge.logic.globalDict
		self.FSM.stateLife += 1
		own = getOwn()
		if own['requestAction'] == 'reg_roll':
			print('requesting early out')
			self.FSM.ToTransition('toreg_opos_to_roll')
		if transPlaying() == False and self.FSM.stateLife > 2:		
			self.FSM.ToTransition(self.FSM.action.parentTrans)
			transEndPlayer(self, FSM)
		else:
			actionPlayer(self, FSM)

	def Exit(self):
		print('exiting: ', type(self).__name__)

class reg_opos_to_roll(State):
	def __init__(self,FSM):
		super(reg_opos_to_roll, self).__init__(FSM) 
		
	def Enter(self):
		print('entering: ', type(self).__name__)
		self.FSM.action = getattr(actionsFSMlist, type(self).__name__) 
		super(reg_opos_to_roll, self).Enter()

		old_state = self.FSM.prevState
		if getCurFrame() != None:	
			print('do the things', old_state.FSM.currentFrame, getCurFrame())
			self.FSM.action.s_se[0] = getCurFrame()
		
	def Execute(self):
		print('executing: ', type(self).__name__)
		self.FSM.stateLife += 1
		if transPlaying() == False and self.FSM.stateLife > 2:		
			self.FSM.ToTransition('toreg_roll')
			transEndPlayer(self, FSM)
		else:
			actionPlayer(self, FSM)	        
	
	def Exit(self):
		print('exiting: ', type(self).__name__)	
					   
class reg_roll_to_left(State):
	def __init__(self,FSM):
		super(reg_roll_to_left, self).__init__(FSM) 
		
	def Enter(self):
		print('entering: ', type(self).__name__)
		self.FSM.action = getattr(actionsFSMlist, type(self).__name__) 
		super(reg_roll_to_left, self).Enter()

		old_state = self.FSM.prevState
		if getCurFrame() != None:	
			print('current frame is', getCurFrame())
			self.FSM.action.s_se[0] = getCurFrame()
		
	def Execute(self):
		print('executing: ', type(self).__name__)
		dict = bge.logic.globalDict
		self.FSM.stateLife += 1
		own = getOwn()
		if own['requestAction'] == 'reg_roll':
			self.FSM.ToTransition('toreg_left_to_roll')
		if transPlaying() == False and self.FSM.stateLife > 2:		
			self.FSM.ToTransition('toreg_left')
			transEndPlayer(self, FSM)
		else:
			actionPlayer(self, FSM)        
	
	def Exit(self):
		print('exiting: ', type(self).__name__)	

class reg_left_to_roll(State):
	def __init__(self,FSM):
		super(reg_left_to_roll, self).__init__(FSM) 
		
	def Enter(self):
		print('entering: ', type(self).__name__)
		self.FSM.action = getattr(actionsFSMlist, type(self).__name__) 
		super(reg_left_to_roll, self).Enter()

		old_state = self.FSM.prevState
		if getCurFrame() != None:	
			print('do the things', old_state.FSM.currentFrame, getCurFrame())
			self.FSM.action.s_se[0] = getCurFrame()
		
	def Execute(self):
		print('executing: ', type(self).__name__)
		dict = bge.logic.globalDict
		self.FSM.stateLife += 1
		if transPlaying() == False and self.FSM.stateLife > 2:		
			self.FSM.ToTransition('toreg_roll')
			transEndPlayer(self, FSM)
		else:
			actionPlayer(self, FSM)	        
	
	def Exit(self):
		print('exiting: ', type(self).__name__)		
					 
#===================================
#====================================						

class FSM(object):
	def __init__ (self, character):

		try:
			self.char = self.char

		except:	

			self.char = character
			self.states = {}
			self.transitions = {}
			self.curState = None
			self.prevState = None
			self.stateLife = 0
			self.currentFrame = 0.0
			self.name = ''
			  
			self.action = []

			print('always init')
	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 StateMachine(Char):
	def __init__(self):
		self.FSM = FSM(self)
		
		##STATES
		self.FSM.AddState('reg_roll', reg_roll(self.FSM))
		self.FSM.AddState('reg_opos', reg_opos(self.FSM))
		self.FSM.AddState('reg_roll_to_opos', reg_roll_to_opos(self.FSM))
		self.FSM.AddState('reg_opos_to_roll', reg_opos_to_roll(self.FSM))
		self.FSM.AddState('reg_left', reg_left(self.FSM))
		self.FSM.AddState('reg_left_to_roll', reg_left_to_roll(self.FSM))
		self.FSM.AddState('reg_roll_to_left', reg_roll_to_left(self.FSM))

		#TRANSITIONS
		self.FSM.AddTransition('toreg_roll', Transition('reg_roll'))
		self.FSM.AddTransition('toreg_opos', Transition('reg_opos'))
		self.FSM.AddTransition('toreg_roll_to_opos', Transition('reg_roll_to_opos'))
		self.FSM.AddTransition('toreg_opos_to_roll', Transition('reg_opos_to_roll'))
		self.FSM.AddTransition('toreg_left', Transition('reg_left'))
		self.FSM.AddTransition('toreg_left_to_roll', Transition('reg_left_to_roll'))
		self.FSM.AddTransition('toreg_roll_to_left', Transition('reg_roll_to_left'))

		if self.FSM.curState == None:
			self.FSM.SetState('reg_roll')
			self.FSM.ToTransition('toreg_roll')
			print('      -= Initializing Action Player State Machine =-')
	
	def Execute(self):
		self.FSM.Execute()    
#====================================     
r = StateMachine()
def main(cont):
	own = cont.owner   
	if 'inited' not in own:
		own['inited'] = True
		own['frame'] = 0
		own['state'] = 'On'
		print('initing')

	r.Execute()    
	own['frame'] += 1
	if interupt_request():
		print('interupt request')