package electrosphere.entity.state.particle;

import org.joml.AxisAngle4f;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import org.joml.Vector3d;

import electrosphere.engine.Globals;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.game.data.particle.ParticleData;

/**
 * Particle component for a client-side particle
 */
public class ClientParticleTree implements BehaviorTree {
    
    //The parent entity
    Entity parent;

    //used to toggle life simulation
    boolean hasLife = true;
    //max life
    int maxLife;
    //current life
    int lifeCurrent;


    //The destination of the particle
    Vector3d destination;

    //the velocity of the particle
    float velocity;

    //the acceleration of the particle
    float acceleration;
    

    /**
     * Constructor
     * @param parent
     * @param params
     */
    private ClientParticleTree(Entity parent, Object ... params){
        if(params.length < 1){
            throw new IllegalArgumentException("No particle data was provided");
        }
        if(params.length < 2){
            throw new IllegalArgumentException("No destination set for the particle");
        }
        ParticleData particleData = (ParticleData)params[0];
        Vector3d destination = (Vector3d)params[1];

        //sets data for the tree
        this.parent = parent;
        this.maxLife = particleData.getMaxLife();
        this.destination = destination;
        this.velocity = particleData.getVelocity();
        this.acceleration = particleData.getAcceleration();
        this.hasLife = particleData.getMaxLife() != null;
        this.lifeCurrent = maxLife;
    }

    public int getMaxLife() {
        return maxLife;
    }

    public int getLifeCurrent() {
        return lifeCurrent;
    }

    public Vector3d getDestination() {
        return destination;
    }

    public float getVelocity() {
        return velocity;
    }

    public float getAcceleration() {
        return acceleration;
    }
    
    @Override
    public void simulate(float deltaTime){
        Vector3d parentPosition = EntityUtils.getPosition(parent);
        parentPosition.add(new Vector3d(destination).mul(velocity));
        velocity = velocity + acceleration;
        if(velocity < 0){
            velocity = 0;
            acceleration = 0;
        }
        if(hasLife){
            lifeCurrent--;
            if(lifeCurrent <= 0){
                ClientEntityUtils.destroyEntity(parent);
            }
        }

        //rotate the model to face the camera
        Matrix4f rotationMatrix = new Matrix4f(Globals.viewMatrix).invert();
        Quaternionf rotation = new Quaternionf(rotationMatrix.getRotation(new AxisAngle4f()));
        EntityUtils.getRotation(parent).set(rotation);
    }

    /**
     * Attaches the client particle tree to the given entity
     * @param parent The parent entity
     * @param params The params
     */
    public static ClientParticleTree attachTree(Entity parent, Object ... params){
        ClientParticleTree rVal = new ClientParticleTree(parent,params);
        parent.putData(EntityDataStrings.TREE_CLIENTPARTICLETREE, rVal);
        Globals.clientSceneWrapper.getScene().registerBehaviorTree(rVal);
        return rVal;
    }

}
