"""
  Peek-A-Boo game inspired by the Boo game of Pablo Barros.

  This version is coded using the cozmo_fsm package and illustrates
  features such as repetitive polling, nested state machines, and a
  completion transition that uses one completing source node to
  terminate a second source (MoveHead) that doesn't complete.
"""

from cozmo_fsm import *

class WaitForPlayer(StateMachineProgram):
    """Wait for player's face to appear and remain visible for a little while."""
    def start(self,event=None):
        self.set_polling_interval(0.2)
        self.faces_found = 0  # initialize before polling starts
        super().start(event)

    def poll(self):
        if self.robot.world.visible_face_count() == 0: return
        self.faces_found += 1
        if self.faces_found > 3:
            self.post_completion()

class WaitForHide(StateNode):
    """Wait for player's face to disappear and remain not visible for a little while."""
    def start(self,event=None):
        self.set_polling_interval(0.2)
        self.faces_not_found = 0  # initialize before polling starts
        super().start(event)

    def poll(self):
        if self.robot.world.visible_face_count() > 0: return
        self.faces_not_found += 1
        if self.faces_not_found > 2:
            self.post_completion()

class HeadAndLiftGesture(StateNode):
    """Move head and lift simultaneously. Finish when head movement completes."""
    def setup(self):
        """
            launch: StateNode() =N=> {move_head, move_lift}
    
            move_head: SetHeadAngle(cozmo.robot.MAX_HEAD_ANGLE)
            move_lift: MoveLift(-3)
    
            {move_head, move_lift} =C(1)=> ParentCompletes()
        """
        
        # Code generated by genfsm on Mon Feb 17 03:10:20 2020:
        
        launch = StateNode() .set_name("launch") .set_parent(self)
        move_head = SetHeadAngle(cozmo.robot.MAX_HEAD_ANGLE) .set_name("move_head") .set_parent(self)
        move_lift = MoveLift(-3) .set_name("move_lift") .set_parent(self)
        parentcompletes1 = ParentCompletes() .set_name("parentcompletes1") .set_parent(self)
        
        nulltrans1 = NullTrans() .set_name("nulltrans1")
        nulltrans1 .add_sources(launch) .add_destinations(move_head,move_lift)
        
        completiontrans1 = CompletionTrans(1) .set_name("completiontrans1")
        completiontrans1 .add_sources(move_head,move_lift) .add_destinations(parentcompletes1)
        
        return self

class Boo(StateNode):
    def setup(self):
        """
            launch: Say("Let's play")
                    =C=> SetHeadAngle(30)
                    =C=> player_appears
    
            player_appears: WaitForPlayer()
                =C=> AnimationNode('anim_freeplay_reacttoface_identified_01_head_angle_40')
                =C=> SetHeadAngle(cozmo.robot.MIN_HEAD_ANGLE)
                =C=> SetHeadAngle(cozmo.robot.MAX_HEAD_ANGLE)
                =C=> player_hides
    
            player_hides: WaitForHide()
                =C=> AnimationNode('anim_hiking_observe_01')
                =C=> HeadAndLiftGesture()
                =C=> player_reappears
    
            player_reappears: WaitForPlayer()
                =C=> AnimationNode('anim_freeplay_reacttoface_like_01')
                =C=> HeadAndLiftGesture()
                =C=> Say("play again")
                =C=> SetHeadAngle(30)
                =C=> player_hides
        """
        
        # Code generated by genfsm on Mon Feb 17 03:10:20 2020:
        
        launch = Say("Let's play") .set_name("launch") .set_parent(self)
        setheadangle1 = SetHeadAngle(30) .set_name("setheadangle1") .set_parent(self)
        player_appears = WaitForPlayer() .set_name("player_appears") .set_parent(self)
        animationnode1 = AnimationNode('anim_freeplay_reacttoface_identified_01_head_angle_40') .set_name("animationnode1") .set_parent(self)
        setheadangle2 = SetHeadAngle(cozmo.robot.MIN_HEAD_ANGLE) .set_name("setheadangle2") .set_parent(self)
        setheadangle3 = SetHeadAngle(cozmo.robot.MAX_HEAD_ANGLE) .set_name("setheadangle3") .set_parent(self)
        player_hides = WaitForHide() .set_name("player_hides") .set_parent(self)
        animationnode2 = AnimationNode('anim_hiking_observe_01') .set_name("animationnode2") .set_parent(self)
        headandliftgesture1 = HeadAndLiftGesture() .set_name("headandliftgesture1") .set_parent(self)
        player_reappears = WaitForPlayer() .set_name("player_reappears") .set_parent(self)
        animationnode3 = AnimationNode('anim_freeplay_reacttoface_like_01') .set_name("animationnode3") .set_parent(self)
        headandliftgesture2 = HeadAndLiftGesture() .set_name("headandliftgesture2") .set_parent(self)
        say1 = Say("play again") .set_name("say1") .set_parent(self)
        setheadangle4 = SetHeadAngle(30) .set_name("setheadangle4") .set_parent(self)
        
        completiontrans2 = CompletionTrans() .set_name("completiontrans2")
        completiontrans2 .add_sources(launch) .add_destinations(setheadangle1)
        
        completiontrans3 = CompletionTrans() .set_name("completiontrans3")
        completiontrans3 .add_sources(setheadangle1) .add_destinations(player_appears)
        
        completiontrans4 = CompletionTrans() .set_name("completiontrans4")
        completiontrans4 .add_sources(player_appears) .add_destinations(animationnode1)
        
        completiontrans5 = CompletionTrans() .set_name("completiontrans5")
        completiontrans5 .add_sources(animationnode1) .add_destinations(setheadangle2)
        
        completiontrans6 = CompletionTrans() .set_name("completiontrans6")
        completiontrans6 .add_sources(setheadangle2) .add_destinations(setheadangle3)
        
        completiontrans7 = CompletionTrans() .set_name("completiontrans7")
        completiontrans7 .add_sources(setheadangle3) .add_destinations(player_hides)
        
        completiontrans8 = CompletionTrans() .set_name("completiontrans8")
        completiontrans8 .add_sources(player_hides) .add_destinations(animationnode2)
        
        completiontrans9 = CompletionTrans() .set_name("completiontrans9")
        completiontrans9 .add_sources(animationnode2) .add_destinations(headandliftgesture1)
        
        completiontrans10 = CompletionTrans() .set_name("completiontrans10")
        completiontrans10 .add_sources(headandliftgesture1) .add_destinations(player_reappears)
        
        completiontrans11 = CompletionTrans() .set_name("completiontrans11")
        completiontrans11 .add_sources(player_reappears) .add_destinations(animationnode3)
        
        completiontrans12 = CompletionTrans() .set_name("completiontrans12")
        completiontrans12 .add_sources(animationnode3) .add_destinations(headandliftgesture2)
        
        completiontrans13 = CompletionTrans() .set_name("completiontrans13")
        completiontrans13 .add_sources(headandliftgesture2) .add_destinations(say1)
        
        completiontrans14 = CompletionTrans() .set_name("completiontrans14")
        completiontrans14 .add_sources(say1) .add_destinations(setheadangle4)
        
        completiontrans15 = CompletionTrans() .set_name("completiontrans15")
        completiontrans15 .add_sources(setheadangle4) .add_destinations(player_hides)
        
        return self
