import bge
import math
from random import randint
from time import clock
dict = bge.logic.globalDict
   

def get_request_state(cur_state):
    if dict['cam_state'] != cur_state:
        print(cur_state)
        print('change cam')
        return 'to' + str(dict['cam_state'])
    else:
        return None

#camera - (Target Object, Min Distance, Max Distance, Height)
def activate_camera(cobj, cmin, cmax, cheight):
    cont = bge.logic.getCurrentController()
    scene = bge.logic.getCurrentScene()
    camActu = cont.actuators['Camera']
    camActu.object = scene.objects[cobj]
    camActu.min = cmin
    camActu.max = cmax
    camActu.height = cheight
    cont.activate(camActu)



#====================================
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
        #cam settings
        self.target = None
        self.min = 0
        self.max = 0

    def Enter(self):
        self.timer = randint(0,5)
        self.startTime = int(clock())
    def Execute(self):
        print('Executing')
    def Exit(self):
        print('Exiting')
        
class WalkCam(State):
    def __init__(self,FSM):
        super(WalkCam, self).__init__(FSM)   
        self.min = 4
        self.max = 5
        self.target = 'player' 
        
    def Enter(self):
        print('Preparing to enter walk cam state.')
        self.FSM.stateLife = 1
        super(WalkCam, self).Enter()
        
    def Execute(self):
        #print('walk cam state', self.FSM.stateLife)
        self.FSM.stateLife += 1
        duration = 50
        #activate_camera('camCube', 2, 3, 1)
        new_state = get_request_state(self.__class__.__name__)
        if new_state:
            self.FSM.ToTransition(new_state)
            print('call new state')                

    def Exit(self):
        print('walk cam state')  

class RollCam(State):
    def __init__(self,FSM):
        super(RollCam, self).__init__(FSM)    
        
    def Enter(self):
        print('Preparing to enter roll cam state')
        self.FSM.stateLife = 1
        super(RollCam, self).Enter()
        
    def Execute(self):
        #print('Eating Breakfast.', self.FSM.stateLife)
        self.FSM.stateLife += 1
        #duration = 500
        if self.FSM.stateLife > 60:
            dict = bge.logic.globalDict
            own = dict['p1c']
            if own['grinding'] == True:
                scene = bge.logic.getCurrentScene()
                ce = scene.objects['cam_helper2']
                ce.worldPosition = own.worldPosition
                ce.worldOrientation = own.worldOrientation
                #ce.applyMovement([-1,0,0], True)
                #activate_camera('camCube', 1.5, 3, 2)
                fliplist = ['reg_tailslide', 'reg_noseslide', 'reg_bsboard', 'fak_tailslide', 'fak_noseslide', 'fak_bsboard']            
                #fliplist = []
                stre = .02
                local = own.worldOrientation.inverted() * (dict['camera'].worldPosition - own.worldPosition) 
                if local.y > 0:
                    rot = 'right'
                else:
                    rot = 'left'       
                print(own['requestAction'])
                yval = 0
                if own['stance'] == True:
                    xval = -1
                else:
                    xval = 1    
                if rot == 'right':
                    yval = 1
                    if own['requestAction'] in fliplist:
                        xval *= -1
                        #print('flipping')
                    dict['camera'].worldPosition = dict['camera'].worldPosition.lerp(ce.worldPosition, stre)
                else:
                    yval = -1
                    if own['requestAction'] in fliplist:
                        xval *= -1
                        print('flipping')
            
                ce.applyMovement([xval,yval,0], True)
                dict['camera'].worldPosition = dict['camera'].worldPosition.lerp(ce.worldPosition, stre)



                # cont = bge.logic.getCurrentController()
                # scene = bge.logic.getCurrentScene()
                # camActu = cont.actuators['Camera']
                # #camActu.object = scene.objects[cobj]
                # camActu.damping = 0
                # #camActu.max = cmax
                # #camActu.height = cheight
                # cont.activate(camActu)


            #activate_camera('camCube', 1.5, 3, 2)
            new_state = get_request_state(self.__class__.__name__)

            if new_state:
                self.FSM.ToTransition(new_state)
                print('call new state') 
                    
    def Exit(self):
        print('Finished RollCaming')          
        
class RagdollCam(State):
    def __init__(self,FSM):
        super(RagdollCam, self).__init__(FSM)    
        
    def Enter(self):
        print('Preparing to RagdollCam state.')
        self.FSM.stateLife = 1
        super(RagdollCam, self).Enter()
        
    def Execute(self):
        #print('Vacumming.', self.FSM.stateLife)
        self.FSM.stateLife += 1
        duration = 6
        new_state = get_request_state(self.__class__.__name__)
        if new_state:
            self.FSM.ToTransition(new_state)
            print('call new state') 
                
    def Exit(self):
        print('Finished RagdollCaming')             
        
        
class PauseCam(State):
    
    def __init__(self,FSM):
        super(PauseCam, self).__init__(FSM)  
        
    def Enter(self):
        print('Starting to PauseCam.')
        super(PauseCam, self).Enter()
        self.FSM.stateLife = 1
        
    def Execute(self):
        #print('PauseCaming.', self.FSM.stateLife)
        self.FSM.stateLife += 1
        new_state = get_request_state(self.__class__.__name__)
        if new_state != None:
            self.FSM.ToTransition(new_state)
            print('call new state') 

    def Exit(self):
        print('Finished PauseCaming.')  

class PauseIdleCam(State):
    
    def __init__(self,FSM):
        super(PauseIdleCam, self).__init__(FSM)  
        
    def Enter(self):
        print('Starting to PauseIdleCam.')
        super(PauseIdleCam, self).Enter()
        self.FSM.stateLife = 1
        
    def Execute(self):
        #print('PauseIdleCaming.', self.FSM.stateLife)
        self.FSM.stateLife += 1
        new_state = get_request_state(self.__class__.__name__)
        if new_state != None:
            self.FSM.ToTransition(new_state)
            print('call new state') 

    def Exit(self):
        print('Finished PauseIdleCaming.')                          
                     
#===================================
                        

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 CameraFSM(Char):
    def __init__(self):
        self.FSM = FSM(self)
        ##STATES
        self.FSM.AddState('WalkCam', WalkCam(self.FSM))
        self.FSM.AddState('RollCam', RollCam(self.FSM))
        self.FSM.AddState('RagdollCam', RagdollCam(self.FSM))
        self.FSM.AddState("PauseCam", PauseCam(self.FSM))
        self.FSM.AddState("PauseIdleCam", PauseIdleCam(self.FSM))

        #TRANSITIONS
        self.FSM.AddTransition('toPauseCam', Transition('PauseCam'))
        self.FSM.AddTransition('toPauseIdleCam', Transition('PauseIdleCam'))
        self.FSM.AddTransition('toWalkCam', Transition('WalkCam'))
        self.FSM.AddTransition('toRollCam', Transition('RollCam'))
        self.FSM.AddTransition('toRagdollCam', Transition('RagdollCam'))
        
        if self.FSM.curState == None:
            self.FSM.SetState('WalkCam')
            print('setting none')
    
    def Execute(self):
        self.FSM.Execute()    
#====================================     
machine = CameraFSM()
def main(cont):
    own = cont.owner   
    if 'FSMinited' not in own:
        own['FSMinited'] = True
        #own['frame'] = 0
        #own['state'] = 'On'
        
        print('FSMiniting')

    machine.Execute()    
    
    #own['frame'] += 1
