package electrosphere.entity.types.collision;

import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.ode4j.ode.DBody;

import electrosphere.collision.CollisionEngine;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.server.datacell.Realm;

/**
 * Collision object utility functions
 */
public class CollisionObjUtils {

    /**
     * Attach a collision object to a provided entity
     * @param entity The entity to attach a collision object to
     * @param collisionObject The jBulletF collision object to attach to the entity
     * @param mass The mass of the collidable
     * @param collidableType The type of collidable we are attaching. For instance, "Terrain", "Creature", "Item", etc. Refer to Collidable class for options.
     */
    public static void clientAttachCollisionObjectToEntity(Entity entity, DBody collisionObject, float mass, String collidableType){
        Vector3d position = EntityUtils.getPosition(entity);
        Quaterniond rotation = EntityUtils.getRotation(entity);
        Collidable collidable = new Collidable(entity, collidableType, true);
        Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(collisionObject, collidable);

        PhysicsEntityUtils.setDBody(entity, collisionObject);

        //update world transform of collision object
        clientPositionCharacter(entity,position,rotation);
        
        entity.putData(EntityDataStrings.COLLISION_ENTITY_COLLISION_OBJECT, collisionObject);
        entity.putData(EntityDataStrings.COLLISION_ENTITY_COLLIDABLE, collidable);
        entity.putData(EntityDataStrings.PHYSICS_MASS, mass);
    }

    /**
     * Attach a collision object to a provided entity
     * @param entity The entity to attach a collision object to
     * @param collisionObject The jBulletF collision object to attach to the entity
     * @param mass The mass of the collidable
     * @param collidableType The type of collidable we are attaching. For instance, "Terrain", "Creature", "Item", etc. Refer to Collidable class for options.
     */
    public static void serverAttachCollisionObjectToEntity(Entity entity, DBody collisionObject, float mass, String collidableType){
        Vector3d position = EntityUtils.getPosition(entity);
        Collidable collidable = new Collidable(entity, collidableType, true);
        Realm realm = Globals.realmManager.getEntityRealm(entity);
        realm.getCollisionEngine().registerCollisionObject(collisionObject, collidable);

        PhysicsEntityUtils.setDBody(entity, collisionObject);

        //update world transform of collision object
        serverPositionCharacter(entity,position);
        
        entity.putData(EntityDataStrings.COLLISION_ENTITY_COLLISION_OBJECT, collisionObject);
        entity.putData(EntityDataStrings.COLLISION_ENTITY_COLLIDABLE, collidable);
        entity.putData(EntityDataStrings.PHYSICS_MASS, mass);
    }
    
    /**
     * Repositions an entity on the server
     * @param e The entity
     * @param position The server
     */
    public static void serverPositionCharacter(Entity e, Vector3d position){
        EntityUtils.getPosition(e).set(position);
        Quaterniond rotation = EntityUtils.getRotation(e);
        DBody body = PhysicsEntityUtils.getDBody(e);
        CollisionEngine collisionEngine = Globals.realmManager.getEntityRealm(e).getCollisionEngine();
        if(body != null){
            PhysicsUtils.setRigidBodyTransform(collisionEngine, position, rotation, body);
        }
    }

    /**
     * Positions an entity on the client
     * @param e The entity
     * @param position The position
     * @param rotation The rotation
     */
    public static void clientPositionCharacter(Entity e, Vector3d position, Quaterniond rotation){
        EntityUtils.getPosition(e).set(position);
        DBody body = PhysicsEntityUtils.getDBody(e);
        if(body != null){
            PhysicsUtils.setRigidBodyTransform(Globals.clientSceneWrapper.getCollisionEngine(), position, rotation, body);
        }
    }
    
    public static Collidable getCollidable(Entity e){
        return (Collidable)e.getData(EntityDataStrings.PHYSICS_COLLIDABLE);
    }

    public static float getMass(Entity e){
        return (float)e.getData(EntityDataStrings.PHYSICS_MASS);
    }

    
}
