package electrosphere.entity.types.item;

import electrosphere.collision.dispatch.CollisionObject;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.GravityTree;
import electrosphere.entity.state.collidable.CollidableTree;
import electrosphere.entity.state.movement.GroundMovementTree;
import electrosphere.entity.types.attach.AttachUtils;
import electrosphere.entity.types.hitbox.HitboxData;
import electrosphere.entity.types.hitbox.HitboxUtils;
import electrosphere.game.collision.PhysicsUtils;
import electrosphere.game.collision.collidable.Collidable;
import electrosphere.game.data.creature.type.CollidableTemplate;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.item.type.Item;
import electrosphere.main.Globals;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.server.Player;
import electrosphere.renderer.Actor;
import electrosphere.renderer.ActorUtils;
import electrosphere.renderer.Model;
import org.joml.Quaternionf;
import org.joml.Vector3d;
import org.joml.Vector3f;

/**
 *
 * @author amaterasu
 */
public class ItemUtils {
    public static Entity spawnBasicItem(String name){
        Item item = Globals.gameConfigCurrent.getItemMap().getItem(name);
        Entity rVal = EntityUtils.spawnDrawableEntity(item.getModelPath());
        if(item.getHitboxes() != null){
            for(HitboxData hitboxdata : item.getHitboxes()){
                Globals.hitboxManager.registerHitbox(HitboxUtils.spawnRegularHitbox(rVal, hitboxdata.getBone(), hitboxdata.getRadius()));
            }
        }
        if(item.getCollidable() != null){
            CollidableTemplate physicsTemplate = item.getCollidable();
            CollisionObject rigidBody;
            Collidable collidable;
            switch(physicsTemplate.getType()){
                case "CYLINDER":
                    rigidBody = PhysicsUtils.getCylinderObject(new Vector3f(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()));
                    collidable = new Collidable(rVal, Collidable.TYPE_ITEM);
                    rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, rigidBody);
                    rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET, new Vector3f(physicsTemplate.getOffsetX(),physicsTemplate.getOffsetY(),physicsTemplate.getOffsetZ()));
                    rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
                    rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
                    rVal.putData(EntityDataStrings.COLLIDABLE_TREE, new CollidableTree(rVal,collidable,rigidBody));
                    Globals.collisionEngine.registerPhysicsEntity(rVal);
                    Globals.collisionEngine.registerDynamicPhysicsEntity(rVal);
                    Globals.collisionEngine.registerCollisionObject(rigidBody, collidable);
                    Globals.entityManager.registerCollidableEntity(rVal);
                    break;
                case "CUBE":
                    rigidBody = PhysicsUtils.getCubeObject(new Vector3f(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()));
                    collidable = new Collidable(rVal, Collidable.TYPE_ITEM);
                    rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, rigidBody);
                    rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET, new Vector3f(physicsTemplate.getOffsetX(),physicsTemplate.getOffsetY(),physicsTemplate.getOffsetZ()));
                    rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
                    rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
                    rVal.putData(EntityDataStrings.COLLIDABLE_TREE, new CollidableTree(rVal,collidable,rigidBody));
                    Globals.collisionEngine.registerPhysicsEntity(rVal);
                    Globals.collisionEngine.registerDynamicPhysicsEntity(rVal);
                    Globals.collisionEngine.registerCollisionObject(rigidBody, collidable);
                    Globals.entityManager.registerCollidableEntity(rVal);
                    break;
            }
        }
        for(String token : item.getTokens()){
            switch(token){
                case "BLENDER_TRANSFORM":
                    ActorUtils.applyBlenderTransformer(rVal);
                    break;
                case "GRAVITY":
                    Collidable collidable = (Collidable)rVal.getData(EntityDataStrings.PHYSICS_COLLIDABLE);
                    CollisionObject collisionObject = (CollisionObject)rVal.getData(EntityDataStrings.PHYSICS_COLLISION_BODY);
                    GravityTree gravityTree = new GravityTree(rVal,collidable,collisionObject);
//                    gravityTree.setCollisionObject(collisionObject, collidable);
                    rVal.putData(EntityDataStrings.GRAVITY_ENTITY, true);
                    rVal.putData(EntityDataStrings.GRAVITY_TREE, gravityTree);
                    Globals.entityManager.registerGravityEntity(rVal);
                    break;
                case "TARGETABLE":
                    Globals.entityManager.registerTargetableEntity(rVal);
                    break;
            }
        }
        rVal.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
        rVal.putData(EntityDataStrings.ITEM_IS_ITEM, true);
        rVal.putData(EntityDataStrings.ITEM_TYPE, name);
//        rVal.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(0.005f,0.005f,0.005f));
//        rVal.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaternionf().identity().rotateY((float)(-Math.PI/2)).rotateZ(-(float)(Math.PI/2)));
        Globals.entityManager.registerItemEntity(rVal);
        return rVal;
    }
    
    public static void removePhysics(Entity item){
        /*
        rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, rigidBody);
                    rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET, new Vector3f(physicsTemplate.getOffsetX(),physicsTemplate.getOffsetY(),physicsTemplate.getOffsetZ()));
                    rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
                    rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE,collidable);
                    rVal.putData(EntityDataStrings.COLLIDABLE_TREE, new CollidableTree(rVal,collidable,rigidBody));
        */
        if(item.getDataKeys().contains(EntityDataStrings.PHYSICS_COLLISION_BODY)){
            item.removeData(EntityDataStrings.PHYSICS_COLLISION_BODY);
        }
        if(item.getDataKeys().contains(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET)){
            item.removeData(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET);
        }
        if(item.getDataKeys().contains(EntityDataStrings.PHYSICS_MODEL_TEMPLATE)){
            item.removeData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE);
        }
        if(item.getDataKeys().contains(EntityDataStrings.PHYSICS_COLLIDABLE)){
            item.removeData(EntityDataStrings.PHYSICS_COLLIDABLE);
        }
        if(item.getDataKeys().contains(EntityDataStrings.COLLIDABLE_TREE)){
            item.removeData(EntityDataStrings.COLLIDABLE_TREE);
        }
    }
    
    public static void updateItemActorAnimation(Entity item){
        Actor actor = EntityUtils.getActor(item);
        if(actor.getCurrentAnimation() == null){
//            Model model;
//            if((model = Globals.assetManager.fetchModel(actor.getModelPath()))!=null){
//                model.describeAllAnimations();
//            }
            actor.playAnimation("Sword|Idle");
        }
    }
    
    public static void sendEntityToPlayer(Player player, Entity item){
        int id = item.getId();
        String type = ItemUtils.getType(item);
        Vector3d position = EntityUtils.getPosition(item);
        NetworkMessage message = EntityMessage.constructCreateMessage(id, EntityDataStrings.ENTITY_CATEGORY_ITEM, type, (float)position.x, (float)position.y, (float)position.z);
        player.addMessage(message);
        if(AttachUtils.isAttached(item)){
            player.addMessage(
                    EntityMessage.constructattachEntityToEntityMessage(
                            item.getId(),
                            AttachUtils.getTargetBone(item),
                            AttachUtils.getParent(item).getId()
                    )
            );
        }
    }
    
    public static boolean isItem(Entity item){
        return item.getDataKeys().contains(EntityDataStrings.ITEM_IS_ITEM);
    }
    
    public static String getType(Entity item){
        return (String)item.getData(EntityDataStrings.ITEM_TYPE);
    }
}
