package electrosphere.entity.state.movement;

import electrosphere.audio.movement.MovementAudioService.InteractionType;
import electrosphere.client.terrain.sampling.ClientVoxelSampler;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.btree.StateTransitionUtil;
import electrosphere.entity.btree.StateTransitionUtil.StateTransitionUtilItem;
import electrosphere.entity.state.AnimationPriorities;
import electrosphere.entity.state.client.firstPerson.FirstPersonTree;
import electrosphere.entity.state.movement.jump.ClientJumpTree;
import electrosphere.game.data.creature.type.movement.FallMovementSystem;
import electrosphere.renderer.actor.Actor;

/**
 * Behavior tree for playing animations when an entity is falling/landing
 */
public class FallTree implements BehaviorTree {

    /**
     * The state of the fall tree
     */
    static enum FallState {
        ACTIVE,
        INACTIVE,
    }

    //the raw data from disk
    FallMovementSystem fallMovementSystem;

    //current state
    FallState state = FallState.INACTIVE;

    //the entity this is attached to
    Entity parent;

    //the related jump tree
    ClientJumpTree jumpTree;

    //The state transition util
    StateTransitionUtil stateTransitionUtil;

    public FallTree(Entity parent, FallMovementSystem fallMovementSystem){
        this.parent = parent;
        this.fallMovementSystem = fallMovementSystem;
        stateTransitionUtil = StateTransitionUtil.create(
            parent,
            false,
            new StateTransitionUtilItem[]{
                StateTransitionUtilItem.create(
                    FallState.ACTIVE,
                    fallMovementSystem.getFallState(),
                    null
                )
            }
        );
    }

    @Override
    public void simulate(float deltaTime) {
        switch(state){
            case ACTIVE:
            stateTransitionUtil.simulate(FallState.ACTIVE);
            break;
            case INACTIVE:
            break;
        }
    }

    /**
     * Starts the falling tree
     */
    public void start(){
        state = FallState.ACTIVE;
    }

    /**
     * Returns the status of the fall tree
     * @return true if falling, false otherwise
     */
    public boolean isFalling(){
        return state == FallState.ACTIVE;
    }

    /**
     * Triggers the falling tree to land
     */
    public void land(){
        if(state != FallState.INACTIVE){
            state = FallState.INACTIVE;
            Actor entityActor = EntityUtils.getActor(parent);
            if(entityActor != null){
                if(
                    !entityActor.isPlayingAnimation() || !entityActor.isPlayingAnimation(fallMovementSystem.getLandState().getAnimation().getNameThirdPerson())
                ){
                    entityActor.playAnimation(fallMovementSystem.getLandState().getAnimation().getNameThirdPerson(),AnimationPriorities.getValue(AnimationPriorities.MOVEMENT_MODIFIER));
                    entityActor.incrementAnimationTime(0.0001);
                }
                FirstPersonTree.conditionallyPlayAnimation(parent, fallMovementSystem.getLandState().getAnimation());
            }
            if(parent == Globals.playerEntity && !Globals.controlHandler.cameraIsThirdPerson()){
                //first person
                Globals.movementAudioService.playAudioPositional(ClientVoxelSampler.getVoxelTypeBeneathEntity(parent), InteractionType.LAND, EntityUtils.getPosition(parent));
                //play first person audio
            } else {
                //play third person audio
                Globals.movementAudioService.playAudioPositional(ClientVoxelSampler.getVoxelTypeBeneathEntity(parent), InteractionType.LAND, EntityUtils.getPosition(parent));
            }
        }
    }

    /**
     * Gets the falling tree state of an entity
     * @param parent the entity
     * @return the state
     */
    public static FallTree getFallTree(Entity parent){
        return (FallTree)parent.getData(EntityDataStrings.FALL_TREE);
    }

    /**
     * Sets the related jump tree
     * @param jumpTree the jump tree that is related to this fall tree (on the same entity)
     */
    public void setJumpTree(ClientJumpTree jumpTree){
        this.jumpTree = jumpTree;
    }
    
}
