package electrosphere.game.simulation;

import electrosphere.entity.types.attach.AttachUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.AttackTree;
import electrosphere.entity.state.GravityTree;
import electrosphere.entity.state.IdleTree;
import electrosphere.entity.state.movement.GroundMovementTree;
import electrosphere.entity.state.ParticleTree;
import electrosphere.entity.state.collidable.CollidableTree;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.hitbox.HitboxUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.entity.state.life.LifeState;
import electrosphere.entity.state.life.LifeUtils;
import electrosphere.entity.types.particle.ParticleUtils;
import electrosphere.game.client.targeting.crosshair.Crosshair;
import electrosphere.main.Globals;
import static electrosphere.main.Main.deltaTime;
import electrosphere.renderer.Actor;
import org.joml.Vector3f;

/**
 *
 * @author amaterasu
 */
public class MicroSimulation {
    
    boolean isReady = false;
    
    public MicroSimulation(){
        isReady = false;
    }
    
    public void simulate(){
        //simulate bullet physics engine step
        Globals.collisionEngine.simulatePhysics(deltaTime);
        //update dynamic entity positions calculated by bullet
//        Globals.collisionEngine.updateDynamicObjectTransforms();
        //list dynamic object positions
//        Globals.collisionEngine.listBodyPositions();
        //simulate ai
        Globals.aiManager.simulate();
        //update actor animations
        for(Entity currentEntity : Globals.entityManager.getDrawable()){
            //fetch actor
            Actor currentActor = EntityUtils.getActor(currentEntity);
            //increment animations
            if(currentActor.getCurrentAnimation() != null){
                currentActor.incrementAnimationTime(deltaTime);
            }
        }
        //make items play idle animation
        for(Entity item : Globals.entityManager.getItemEntities()){
            ItemUtils.updateItemActorAnimation(item);
        }
        //simulate creature behavior trees
        for(Entity currentMoveable : Globals.entityManager.getMoveable()){
            GroundMovementTree behaviorTree = CreatureUtils.getEntityMovementTree(currentMoveable);
            behaviorTree.simulate();
        }
        //simulate creature gravity trees
        for(Entity currentGravity : Globals.entityManager.getGravityEntities()){
            GravityTree gravityTree = (GravityTree)currentGravity.getData(EntityDataStrings.GRAVITY_TREE);
            gravityTree.simulate(deltaTime);
        }
        //attacker behavior tree
        for(Entity currentAttacker : Globals.entityManager.getAttackerEntities()){
            AttackTree attackTree = CreatureUtils.getAttackTree(currentAttacker);
            attackTree.simulate();
        }
        //idle behavior tree
        for(Entity currentIdler : Globals.entityManager.getCreatureEntities()){
            IdleTree idleTree = CreatureUtils.getIdleTree(currentIdler);
            idleTree.simulate();
        }
        //life state updates
        for(Entity lifeStateEntity : Globals.entityManager.getLifeStateEntities()){
            LifeState lifeState = LifeUtils.getLifeState(lifeStateEntity);
            lifeState.simulate();
        }
        //particle state updates
        for(Entity particle : Globals.entityManager.getParticles()){
            ParticleTree tree = ParticleUtils.getParticleTree(particle);
            tree.simulate();
            ParticleUtils.makeParticleBillboardFaceCamera(particle);
        }
        //update attached entity positions
        AttachUtils.updateAttachedEntityPositions();
        //update hitbox positions
        for(Entity currentHitbox : Globals.hitboxManager.getAllHitboxes()){
            HitboxUtils.updatePosition(currentHitbox);
        }
        //collide hitboxes
        for(Entity currentHitbox : Globals.hitboxManager.getAllHitboxes()){
            if(isReady){
                HitboxUtils.collideEntities(currentHitbox);
            }
        }
        //tally collidables and offset position accordingly
        for(Entity currentCollidable : Globals.entityManager.getCollidables()){
            CollidableTree tree = EntityUtils.getCollidableTree(currentCollidable);
            tree.simulate();
        }
        //targeting crosshair
        if(Globals.RUN_CLIENT){
            Crosshair.checkTargetable();
            Crosshair.updateTargetCrosshairPosition();
        }
        //clear collidable impulse lists
        Globals.collisionEngine.clearCollidableImpulseLists();
        //delete all client side entities that aren't in visible chunks
        if(Globals.RUN_CLIENT){
            Globals.entityManager.clearOutOfBoundsEntities();
        }
        //data cell manager update
        if(Globals.dataCellManager != null){
            boolean playerHasChangedChunk = Globals.dataCellManager.updatePlayerPositions();
            if(playerHasChangedChunk){
                Globals.dataCellManager.unloadPlayerlessChunks();
            }
        }
    }
    
    public boolean isReady(){
        return isReady;
    }
    
    public void setReady(boolean ready){
        isReady = ready;
    }
    
    public void freeze(){
        isReady = false;
    }
    
    public void unfreeze(){
        isReady = true;
    }
    
}
