package electrosphere.client.ui.menu.debug.entity;

import org.ode4j.ode.DBody;
import org.ode4j.ode.DBox;
import org.ode4j.ode.DCylinder;
import org.ode4j.ode.DGeom;
import org.ode4j.ode.DMass;

import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.data.collidable.CollidableTemplate;
import electrosphere.server.datacell.utils.EntityLookupUtils;
import imgui.ImGui;

/**
 * Tab for both exploring and editing physics on this entity
 */
public class ImGuiEntityPhysicsTab {

    /**
     * The minimum offset
     */
    static final float MIN_OFFSET = -10;

    /**
     * The maximum offset
     */
    static final float MAX_OFFSET = 10;

    /**
     * Minimum mass value
     */
    static final float MIN_MASS = 0;

    /**
     * Maximum mass value
     */
    static final float MAX_MASS = 1.0f;

    /**
     * Storage for the modified scale of the collidable
     */
    static float[] scale = new float[3];

    /**
     * Storage for the modified offset of the collidable
     */
    static float[] offset = new float[3];

    /**
     * Radius slider
     */
    static float[] radius = new float[1];

    /**
     * Length slider
     */
    static float[] length = new float[1];

    /**
     * Mass slider
     */
    static float[] mass = new float[1];
    
    /**
     * Physics view
     */
    protected static void drawPhysicsView(boolean show, Entity detailViewEntity){
        if(show && ImGui.collapsingHeader("Physics Details")){
            ImGui.indent();
            if(PhysicsEntityUtils.getDBody(detailViewEntity) != null){
                DBody physicsBody = PhysicsEntityUtils.getDBody(detailViewEntity);
                if(physicsBody != null){
                    ImGui.text("Position: " + EntityUtils.getPosition(detailViewEntity));
                    ImGui.text("Rotation: " + EntityUtils.getRotation(detailViewEntity));
                    ImGui.text("Velocity: " + physicsBody.getLinearVel());
                    ImGui.text("Force: " + physicsBody.getForce());
                    ImGui.text("Angular Velocity: " + physicsBody.getAngularVel());
                    ImGui.text("Torque: " + physicsBody.getTorque());
                    ImGui.text("Move Vector: " + CreatureUtils.getFacingVector(detailViewEntity));
                    ImGui.text("Velocity: " + CreatureUtils.getVelocity(detailViewEntity));
                }
                //synchronized data
                if(
                    Globals.clientSceneWrapper.getScene().getEntityFromId(detailViewEntity.getId()) != null &&
                    Globals.clientSceneWrapper.mapClientToServerId(detailViewEntity.getId()) != -1
                ){
                    //detailViewEntity is a client entity
                    //get server entity
                    int serverIdForClientEntity = Globals.clientSceneWrapper.mapClientToServerId(detailViewEntity.getId());
                    Entity serverEntity = EntityLookupUtils.getEntityById(serverIdForClientEntity);
                    DBody serverPhysicsBody = PhysicsEntityUtils.getDBody(serverEntity);
                    if(serverPhysicsBody != null){
                        ImGui.newLine();
                        ImGui.text("Linked server entity:");
                        ImGui.text("Position (Server): " + EntityUtils.getPosition(serverEntity));
                        ImGui.text("Rotation (Server): " + EntityUtils.getRotation(serverEntity));
                        ImGui.text("Velocity (Server): " + serverPhysicsBody.getLinearVel());
                        ImGui.text("Force (Server): " + serverPhysicsBody.getForce());
                        ImGui.text("Angular Velocity: " + serverPhysicsBody.getAngularVel());
                        ImGui.text("Torque: " + serverPhysicsBody.getTorque());
                        ImGui.text("Move Vector (Server): "+ CreatureUtils.getFacingVector(serverEntity));
                        ImGui.text("Velocity (Server): " + CreatureUtils.getVelocity(serverEntity));
                    }
                } else if(Globals.clientSceneWrapper.containsServerId(detailViewEntity.getId())){
                    //detailViewEntity is a server entity
                    //get client entity
                    int clientId = Globals.clientSceneWrapper.mapServerToClientId(detailViewEntity.getId());
                    Entity clientEntity = Globals.clientSceneWrapper.getScene().getEntityFromId(clientId);
                    DBody clientPhysicsBody = PhysicsEntityUtils.getDBody(clientEntity);
                    if(clientPhysicsBody != null){
                        ImGui.newLine();
                        ImGui.text("Linked client entity:");
                        ImGui.text("Position (Client): " + EntityUtils.getPosition(clientEntity));
                        ImGui.text("Rotation (Client): " + EntityUtils.getRotation(clientEntity));
                        ImGui.text("Velocity (Client): " + clientPhysicsBody.getLinearVel());
                        ImGui.text("Force (Client): " + clientPhysicsBody.getForce());
                        ImGui.text("Angular Velocity: " + clientPhysicsBody.getAngularVel());
                        ImGui.text("Torque: " + clientPhysicsBody.getTorque());
                        ImGui.text("Move Vector (Client): " + CreatureUtils.getFacingVector(clientEntity));
                        ImGui.text("Velocity (Client): " + CreatureUtils.getVelocity(clientEntity));
                    }
                }
                //Collidable editing
                if(physicsBody != null && physicsBody.getFirstGeom() != null && ImGui.collapsingHeader("Modify")){
                    DGeom geom = physicsBody.getFirstGeom();
                    CollidableTemplate template = (CollidableTemplate)detailViewEntity.getData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE);
                    if(geom instanceof DBox){
                        DBox box = (DBox)geom;
                        if(ImGui.sliderFloat3("Offset", offset, MIN_OFFSET, MAX_OFFSET)){
                            box.setOffsetPosition(offset[0], offset[1], offset[2]);
                            template.setOffsetX(offset[0]);
                            template.setOffsetY(offset[1]);
                            template.setOffsetZ(offset[2]);
                        }
                        if(ImGui.sliderFloat3("Scale",scale,MIN_OFFSET,MAX_OFFSET)){
                            box.setLengths(scale[0], scale[1], scale[2]);
                            template.setDimension1(scale[0]);
                            template.setDimension2(scale[1]);
                            template.setDimension3(scale[2]);
                        }
                        if(physicsBody.getMass() instanceof DMass && ImGui.sliderFloat("Mass",mass,MIN_MASS,MAX_MASS)){
                            DMass massObj = (DMass)physicsBody.getMass();
                            float adjusted = (float)Math.log(mass[0] + 1);
                            massObj.setMass(adjusted);
                        }
                    } else if(geom instanceof DCylinder){
                        DCylinder cylinder = (DCylinder)geom;
                        if(ImGui.sliderFloat3("Offset", offset, MIN_OFFSET, MAX_OFFSET)){
                            cylinder.setOffsetPosition(offset[0], offset[1], offset[2]);
                            template.setOffsetX(offset[0]);
                            template.setOffsetY(offset[1]);
                            template.setOffsetZ(offset[2]);
                        }
                        if(ImGui.sliderFloat("Radius",radius,MIN_OFFSET,MAX_OFFSET)){
                            cylinder.setParams(radius[0], cylinder.getLength());
                            template.setDimension1(radius[0]);
                        }
                        if(ImGui.sliderFloat("Length",length,MIN_OFFSET,MAX_OFFSET)){
                            cylinder.setParams(cylinder.getRadius(), length[0]);
                            template.setDimension2(length[0]);
                        }
                        if(physicsBody.getMass() instanceof DMass && ImGui.sliderFloat("Mass",mass,MIN_MASS,MAX_MASS)){
                            DMass massObj = (DMass)physicsBody.getMass();
                            float adjusted = (float)Math.log(mass[0] + 1);
                            massObj.setMass(adjusted);
                        }
                    } else {
                        throw new Error("Unsupported geom type! " + geom);
                    }
                }
            }
            ImGui.unindent();
        }
    }

}
