package electrosphere.server.simulation;

import electrosphere.entity.types.attach.AttachUtils;

import java.util.Set;

import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.collidable.ServerCollidableTree;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.entity.types.particle.ParticleUtils;
import electrosphere.server.datacell.ServerDataCell;
import electrosphere.server.poseactor.PoseActor;

/**
 * Server-side micro-scale simulation
 */
public class MicroSimulation {
    
    boolean isReady = false;
    
    public MicroSimulation(){
        isReady = false;
    }
    
    /**
     * Simulates a provided data cell
     * @param dataCell The data cell
     */
    public void simulate(ServerDataCell dataCell){
        if(dataCell.isReady()){
            //simulate ai
            Globals.aiManager.simulate();
            //update actor animations
            Set<Entity> poseableEntities = dataCell.getScene().getEntitiesWithTag(EntityTags.POSEABLE);
            if(poseableEntities != null){
                for(Entity currentEntity : dataCell.getScene().getEntitiesWithTag(EntityTags.POSEABLE)){
                    //fetch actor
                    PoseActor currentPoseActor = EntityUtils.getPoseActor(currentEntity);
                    //increment animations
                    if(currentPoseActor.isPlayingAnimation()){
                        currentPoseActor.incrementAnimationTime(Globals.timekeeper.getSimFrameTime());
                    }
                }
            }
            //make items play idle animation
            for(Entity item : dataCell.getScene().getEntitiesWithTag(EntityTags.ITEM)){
                ItemUtils.updateItemPoseActorAnimation(item);
            }
            //particle state updates
            for(Entity particle : dataCell.getScene().getEntitiesWithTag(EntityTags.PARTICLE)){
                // ParticleTree tree = ParticleUtils.getParticleTree(particle);
                // tree.simulate(Main.deltaFrames);
                ParticleUtils.makeParticleBillboardFaceCamera(particle);
            }
            //simulate behavior trees
            dataCell.getScene().simulateBehaviorTrees((float)Globals.timekeeper.getSimFrameTime());
            //update attached entity positions
            //!!This must come after simulating behavior trees!!
            //if it does not come after queueing animations, the attach positions might not represent the animation of the parent
            AttachUtils.serverUpdateAttachedEntityPositions(dataCell);
            //sum collidable impulses
            for(Entity collidable : dataCell.getScene().getEntitiesWithTag(EntityTags.COLLIDABLE)){
                ServerCollidableTree.getServerCollidableTree(collidable).simulate((float)Globals.timekeeper.getSimFrameTime());
            }
        }
    }
    
    public boolean isReady(){
        return isReady;
    }
    
    public void setReady(boolean ready){
        isReady = ready;
    }
    
    public void freeze(){
        isReady = false;
    }
    
    public void unfreeze(){
        isReady = true;
    }
    
}
