package electrosphere.entity.state;

import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.hitbox.HitboxUtils;
import electrosphere.game.data.creature.type.AttackMove;
import electrosphere.main.Globals;
import electrosphere.net.parser.net.message.EntityMessage;
import electrosphere.renderer.Actor;
import electrosphere.renderer.anim.Animation;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Vector3d;
import org.joml.Vector3f;

public class AttackTree {
    
    public static enum AttackTreeState {
        WINDUP,
        ATTACK,
        COOLDOWN,
        IDLE,
    }
    
    AttackTreeState state;
    
    Entity parent;
    
    CopyOnWriteArrayList<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList();
    
    long lastUpdateTime = 0;
    
    int frameCurrent;
    
    int damageStartFrame = 1;
    int damageEndFrame = 2;
    
    String animationName = "SwingWeapon";
    
    int maxFrame = 60;
    
    public AttackTree(Entity e){
        state = AttackTreeState.IDLE;
        parent = e;
    }
    
    public AttackTreeState getState(){
        return state;
    }
    
    public void start(String attackType){
        parent.putData(EntityDataStrings.ATTACK_MOVE_TYPE_ACTIVE, attackType);
        AttackMove currentMove;
        switch(attackType){
            case EntityDataStrings.ATTACK_MOVE_TYPE_MELEE_SWING_ONE_HAND:
                currentMove = (AttackMove)parent.getData(EntityDataStrings.ATTACK_MOVE_TYPE_MELEE_SWING_ONE_HAND);
                damageStartFrame = currentMove.getDamageStartFrame();
                damageEndFrame = currentMove.getDamageEndFrame();
                animationName = currentMove.getAnimationName();
                break;
        }
        //TODO: check if can start moving
        state = AttackTreeState.WINDUP;
        frameCurrent = 0;
    }
    
    public void interrupt(){
        state = AttackTreeState.IDLE;
    }
    
    public void slowdown(){
        state = AttackTreeState.COOLDOWN;
    }
    
    public void simulate(){
        float velocity = CreatureUtils.getVelocity(parent);
        Actor entityActor = EntityUtils.getActor(parent);
        Vector3d position = EntityUtils.getPosition(parent);
        Vector3f movementVector = CreatureUtils.getMovementVector(parent);
        
        //parse attached network messages
        for(EntityMessage message : networkMessageQueue){
            networkMessageQueue.remove(message);
//            System.out.println("MOVE to " + message.getX() + " " + message.getY() + " " + message.getZ());
            long updateTime = message.gettime();
            switch(message.getMessageSubtype()){
                case ATTACKUPDATE:
                    if(updateTime > lastUpdateTime){
                        lastUpdateTime = updateTime;
                        switch(message.gettreeState()){
                         case 0:
                                state = AttackTreeState.WINDUP;
                                frameCurrent = 0;
    //                            System.out.println("Set state STARTUP");
                                break;
                            case 1:
                                frameCurrent = damageStartFrame+1;
                                state = AttackTreeState.ATTACK;
    //                            System.out.println("Set state MOVE");
                                break;
                            case 2:
                                frameCurrent = damageEndFrame+1;
                                state = AttackTreeState.COOLDOWN;
    //                            System.out.println("Set state SLOWDOWN");
                                break;
                            case 3:
                                frameCurrent = 60;
                                state = AttackTreeState.IDLE;
    //                            System.out.println("Set state IDLE");
                                break;
                        }
                    }
                    EntityUtils.getPosition(parent).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
                    CreatureUtils.setMovementVector(parent, new Vector3f(message.getrotationX(),message.getrotationY(),message.getrotationZ()));
                    break;
            }
        }
        
        //state machine
        switch(state){
            case WINDUP:
                if(entityActor != null){
                    if(!entityActor.isPlayingAnimation() || !entityActor.getCurrentAnimation().equals(animationName)){
                        entityActor.playAnimation(animationName);
                        entityActor.incrementAnimationTime(0.01);
                    }
                }
                frameCurrent++;
                if(frameCurrent > damageStartFrame){
                    state = AttackTreeState.ATTACK;
                }
                if(Globals.RUN_SERVER){
                    Globals.server.broadcastMessage(
                            EntityMessage.constructattackUpdateMessage(
                                    parent.getId(),
                                    System.currentTimeMillis(),
                                    (float)position.x,
                                    (float)position.y,
                                    (float)position.z,
                                    movementVector.x,
                                    movementVector.y,
                                    movementVector.z,
                                    velocity,
                                    0
                            )
                    );
                } else if(Globals.RUN_CLIENT && parent.getId() == Globals.clientCharacterID){
                    Globals.clientConnection.queueOutgoingMessage(
                            EntityMessage.constructattackUpdateMessage(
                                    parent.getId(),
                                    System.currentTimeMillis(),
                                    (float)position.x,
                                    (float)position.y,
                                    (float)position.z,
                                    movementVector.x,
                                    movementVector.y,
                                    movementVector.z,
                                    velocity,
                                    0
                            )
                    );
                }
                break;
            case ATTACK:
                if(parent.getDataKeys().contains(EntityDataStrings.ATTACH_CHILDREN_LIST)){
                    List<Entity> attachedEntities = (List<Entity>)parent.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
                    for(Entity currentAttached : attachedEntities){
                        if(currentAttached.getDataKeys().contains(EntityDataStrings.ITEM_IS_ITEM)){
                            for(Entity hitbox : Globals.hitboxManager.getAllHitboxes()){
                                if(hitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT) == currentAttached){
                                    HitboxUtils.getHitboxData(hitbox).setActive(true);
                                }
                            }
                        }
                    }
                }
                frameCurrent++;
                if(frameCurrent > damageEndFrame){
                    state = AttackTreeState.COOLDOWN;
                }
                if(Globals.RUN_SERVER){
                    Globals.server.broadcastMessage(
                            EntityMessage.constructattackUpdateMessage(
                                    parent.getId(),
                                    System.currentTimeMillis(),
                                    (float)position.x,
                                    (float)position.y,
                                    (float)position.z,
                                    movementVector.x,
                                    movementVector.y,
                                    movementVector.z,
                                    velocity,
                                    1
                            )
                    );
                } else if(Globals.RUN_CLIENT && parent.getId() == Globals.clientCharacterID){
                    Globals.clientConnection.queueOutgoingMessage(
                            EntityMessage.constructattackUpdateMessage(
                                    parent.getId(),
                                    System.currentTimeMillis(),
                                    (float)position.x,
                                    (float)position.y,
                                    (float)position.z,
                                    movementVector.x,
                                    movementVector.y,
                                    movementVector.z,
                                    velocity,
                                    1
                            )
                    );
                }
                break;
            case COOLDOWN:
                if(parent.getDataKeys().contains(EntityDataStrings.ATTACH_CHILDREN_LIST)){
                    List<Entity> attachedEntities = (List<Entity>)parent.getData(EntityDataStrings.ATTACH_CHILDREN_LIST);
                    for(Entity currentAttached : attachedEntities){
                        if(currentAttached.getDataKeys().contains(EntityDataStrings.ITEM_IS_ITEM)){
                            for(Entity hitbox : Globals.hitboxManager.getAllHitboxes()){
                                if(hitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT) == currentAttached){
                                    HitboxUtils.getHitboxData(hitbox).setActive(false);
                                }
                            }
                        }
                    }
                }
                frameCurrent++;
                if(frameCurrent > 60){
                    state = AttackTreeState.IDLE;
                    frameCurrent = 0;
                }
                if(Globals.RUN_SERVER){
                    Globals.server.broadcastMessage(
                            EntityMessage.constructattackUpdateMessage(
                                    parent.getId(),
                                    System.currentTimeMillis(),
                                    (float)position.x,
                                    (float)position.y,
                                    (float)position.z,
                                    movementVector.x,
                                    movementVector.y,
                                    movementVector.z,
                                    velocity,
                                    2
                            )
                    );
                } else if(Globals.RUN_CLIENT && parent.getId() == Globals.clientCharacterID){
                    Globals.clientConnection.queueOutgoingMessage(
                            EntityMessage.constructattackUpdateMessage(
                                    parent.getId(),
                                    System.currentTimeMillis(),
                                    (float)position.x,
                                    (float)position.y,
                                    (float)position.z,
                                    movementVector.x,
                                    movementVector.y,
                                    movementVector.z,
                                    velocity,
                                    2
                            )
                    );
                }
                break;
            case IDLE:
                break;
        }
    }

    public void addNetworkMessage(EntityMessage networkMessage) {
        networkMessageQueue.add(networkMessage);
    }
    
}
