// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.npc.role;

import javax.annotation.Nullable;
import java.util.EnumSet;
import com.hypixel.hytale.server.core.modules.entitystats.EntityStatValue;
import com.hypixel.hytale.server.core.inventory.Inventory;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.npc.role.support.MarkedEntitySupport;
import com.hypixel.hytale.protocol.MovementStates;
import com.hypixel.hytale.server.core.entity.nameplate.Nameplate;
import com.hypixel.hytale.server.core.modules.physics.component.Velocity;
import com.hypixel.hytale.server.core.modules.entitystats.asset.DefaultEntityStatTypes;
import com.hypixel.hytale.server.core.modules.entitystats.EntityStatMap;
import com.hypixel.hytale.server.npc.util.InventoryHelper;
import com.hypixel.hytale.server.spawning.util.LightRangePredicate;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.server.core.universe.world.chunk.BlockChunk;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.protocol.AnimationSlot;
import com.hypixel.hytale.server.core.entity.movement.MovementStatesComponent;
import com.hypixel.hytale.server.core.modules.entity.component.ActiveAnimationComponent;
import java.time.temporal.TemporalField;
import java.time.temporal.ChronoField;
import com.hypixel.hytale.server.core.modules.time.WorldTimeResource;
import com.hypixel.hytale.server.flock.FlockMembership;
import com.hypixel.hytale.server.npc.entities.NPCEntity;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.ArchetypeChunk;
import javax.annotation.Nonnull;

public class RoleDebugDisplay
{
    protected boolean debugDisplayState;
    protected boolean debugDisplayTime;
    protected boolean debugDisplayFlock;
    protected boolean debugDisplayAnim;
    protected boolean debugDisplayLockedTarget;
    protected boolean debugDisplayLightLevel;
    protected boolean debugDisplayFreeSlots;
    protected boolean debugDisplayCustom;
    protected boolean debugDisplayPathFinder;
    protected boolean debugDisplayHP;
    protected boolean debugDisplayStamina;
    protected boolean debugDisplaySpeed;
    protected boolean debugDisplayInternalId;
    protected boolean debugDisplayName;
    @Nonnull
    protected StringBuilder debugDisplay;
    
    private RoleDebugDisplay() {
        this.debugDisplay = new StringBuilder(20);
    }
    
    public void display(@Nonnull final Role role, final int index, @Nonnull final ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull final CommandBuffer<EntityStore> commandBuffer) {
        final NPCEntity npcComponent = archetypeChunk.getComponent(index, NPCEntity.getComponentType());
        assert npcComponent != null;
        if (this.debugDisplayInternalId) {
            this.debugDisplay.append("ID-").append(archetypeChunk.getReferenceTo(index).getIndex()).append(" ");
        }
        if (this.debugDisplayName) {
            this.debugDisplay.append(" Role(").append(role.getRoleName()).append(")");
        }
        if (this.debugDisplayState) {
            role.getStateSupport().appendStateName(this.debugDisplay);
        }
        if (this.debugDisplayFlock) {
            final FlockMembership flockMembershipComponent = archetypeChunk.getComponent(index, FlockMembership.getComponentType());
            if (flockMembershipComponent != null) {
                if (flockMembershipComponent.getMembershipType().isActingAsLeader()) {
                    this.debugDisplay.append(" LDR");
                }
                else {
                    this.debugDisplay.append(" FLK");
                }
            }
        }
        final WorldTimeResource worldTimeResource = commandBuffer.getResource(WorldTimeResource.getResourceType());
        if (this.debugDisplayTime) {
            final double dayProgress = 24 * worldTimeResource.getGameDateTime().get(ChronoField.SECOND_OF_DAY) / (double)WorldTimeResource.SECONDS_PER_DAY;
            this.debugDisplay.append(' ').append((int)(100.0 * dayProgress) / 100.0);
        }
        if (this.debugDisplayAnim) {
            final ActiveAnimationComponent activeAnimationComponent = archetypeChunk.getComponent(index, ActiveAnimationComponent.getComponentType());
            assert activeAnimationComponent != null;
            final String[] activeAnimations = activeAnimationComponent.getActiveAnimations();
            final MovementStates movementStates = archetypeChunk.getComponent(index, MovementStatesComponent.getComponentType()).getMovementStates();
            this.debugDisplay.append(" M:");
            this.debugDisplay.append(movementStates.idle ? 'I' : '-');
            this.debugDisplay.append(movementStates.horizontalIdle ? 'H' : '-');
            this.debugDisplay.append(movementStates.running ? 'R' : '-');
            this.debugDisplay.append(movementStates.climbing ? 'C' : '-');
            this.debugDisplay.append(movementStates.jumping ? 'J' : '-');
            this.debugDisplay.append(movementStates.falling ? 'F' : '-');
            this.debugDisplay.append(movementStates.crouching ? 'c' : '-');
            this.debugDisplay.append(movementStates.flying ? 'f' : '-');
            this.debugDisplay.append(movementStates.swimming ? 's' : '-');
            this.debugDisplay.append(movementStates.swimJumping ? 'S' : '-');
            this.debugDisplay.append(movementStates.onGround ? 'o' : '-');
            this.debugDisplay.append(movementStates.inFluid ? 'w' : '-');
            String animationId = activeAnimations[AnimationSlot.Status.ordinal()];
            this.debugDisplay.append(" S:").append((animationId != null) ? animationId : "-");
            animationId = activeAnimations[AnimationSlot.Action.ordinal()];
            this.debugDisplay.append(" A:").append((animationId != null) ? animationId : "-");
            animationId = activeAnimations[AnimationSlot.Face.ordinal()];
            this.debugDisplay.append(" F:").append((animationId != null) ? animationId : "-");
        }
        if (this.debugDisplayLockedTarget) {
            final MarkedEntitySupport markedEntitySupport = role.getMarkedEntitySupport();
            for (int targetSlotCount = markedEntitySupport.getMarkedEntitySlotCount(), i = 0; i < targetSlotCount; ++i) {
                final String slotName = markedEntitySupport.getSlotName(i);
                final Ref<EntityStore> targetRef = markedEntitySupport.getMarkedEntityRef(i);
                if (targetRef == null) {
                    this.debugDisplay.append(" T(").append(slotName).append("):-");
                }
                else {
                    final PlayerRef targetPlayerRefComponent = commandBuffer.getComponent(targetRef, PlayerRef.getComponentType());
                    final NPCEntity targetNpcComponent = commandBuffer.getComponent(targetRef, NPCEntity.getComponentType());
                    if (targetPlayerRefComponent != null) {
                        this.debugDisplay.append(" TP(").append(slotName).append("):").append(targetPlayerRefComponent.getUsername());
                    }
                    else if (targetNpcComponent != null) {
                        String roleName = targetNpcComponent.getRoleName();
                        if (roleName == null || roleName.isEmpty()) {
                            roleName = "???";
                        }
                        this.debugDisplay.append(" T(").append(slotName).append("):").append(roleName);
                    }
                    else {
                        this.debugDisplay.append(" T(").append(slotName).append("):?");
                    }
                }
            }
        }
        if (this.debugDisplayLightLevel) {
            final TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType());
            assert transformComponent != null;
            final Ref<ChunkStore> chunkRef = transformComponent.getChunkRef();
            if (chunkRef != null && chunkRef.isValid()) {
                final World world = commandBuffer.getExternalData().getWorld();
                final Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
                final BlockChunk blockChunkComponent = chunkStore.getComponent(chunkRef, BlockChunk.getComponentType());
                assert blockChunkComponent != null;
                final Vector3d position = transformComponent.getPosition();
                final int x = MathUtil.floor(position.getX());
                final int y = MathUtil.floor(position.getY());
                final int z = MathUtil.floor(position.getZ());
                final double sunlightFactor = worldTimeResource.getSunlightFactor();
                this.debugDisplay.append(" LL:").append(LightRangePredicate.lightToPrecentage(LightRangePredicate.calculateLightValue(blockChunkComponent, x, y, z, sunlightFactor))).append('/').append(LightRangePredicate.lightToPrecentage(blockChunkComponent.getSkyLight(x, y, z))).append('/').append(LightRangePredicate.lightToPrecentage((byte)(blockChunkComponent.getSkyLight(x, y, z) * sunlightFactor))).append('/').append(LightRangePredicate.lightToPrecentage(blockChunkComponent.getRedBlockLight(x, y, z))).append('/').append(LightRangePredicate.lightToPrecentage(blockChunkComponent.getGreenBlockLight(x, y, z))).append('/').append(LightRangePredicate.lightToPrecentage(blockChunkComponent.getBlueBlockLight(x, y, z)));
            }
        }
        final String displayPathfinderString = role.getDebugSupport().pollDisplayPathfinderString();
        if (this.debugDisplayPathFinder && displayPathfinderString != null && !displayPathfinderString.isEmpty()) {
            this.debugDisplay.append(this.debugDisplay.isEmpty() ? "PF:" : " PF:").append(displayPathfinderString);
        }
        final String customString = role.getDebugSupport().pollDisplayCustomString();
        if (this.debugDisplayCustom && customString != null && !customString.isEmpty()) {
            if (!this.debugDisplay.isEmpty()) {
                this.debugDisplay.append(' ');
            }
            this.debugDisplay.append(customString);
        }
        if (this.debugDisplayFreeSlots) {
            final Inventory inventory = npcComponent.getInventory();
            final int hotbarFreeSlots = InventoryHelper.countFreeSlots(inventory.getHotbar());
            final int inventoryFreeSlots = InventoryHelper.countFreeSlots(inventory.getStorage());
            this.debugDisplay.append(" FS:").append(hotbarFreeSlots).append('/').append(inventoryFreeSlots);
        }
        if (this.debugDisplayHP) {
            final EntityStatMap entityStatsComponent = archetypeChunk.getComponent(index, EntityStatMap.getComponentType());
            assert entityStatsComponent != null;
            final EntityStatValue healthValue = entityStatsComponent.get(DefaultEntityStatTypes.getHealth());
            if (healthValue == null) {
                this.debugDisplay.append(" HP: N/A");
            }
            else {
                this.debugDisplay.append(" HP:").append(healthValue.get()).append('/').append(healthValue.getMax());
            }
        }
        if (this.debugDisplayStamina) {
            final EntityStatMap entityStatsComponent = archetypeChunk.getComponent(index, EntityStatMap.getComponentType());
            assert entityStatsComponent != null;
            final EntityStatValue staminaValue = entityStatsComponent.get(DefaultEntityStatTypes.getStamina());
            if (staminaValue == null) {
                this.debugDisplay.append(" Stamina: N/A");
            }
            else {
                this.debugDisplay.append(" Stamina:").append(staminaValue.get()).append('/').append(staminaValue.getMax());
            }
        }
        if (this.debugDisplaySpeed) {
            final Velocity velocityComponent = archetypeChunk.getComponent(index, Velocity.getComponentType());
            assert velocityComponent != null;
            this.debugDisplay.append(" SPD:").append(MathUtil.round(velocityComponent.getSpeed(), 1));
        }
        if (!this.debugDisplay.isEmpty()) {
            final Nameplate nameplateComponent = archetypeChunk.getComponent(index, Nameplate.getComponentType());
            if (nameplateComponent != null) {
                nameplateComponent.setText(this.debugDisplay.toString());
            }
            else {
                final Ref<EntityStore> ref = archetypeChunk.getReferenceTo(index);
                commandBuffer.addComponent(ref, Nameplate.getComponentType(), new Nameplate(this.debugDisplay.toString()));
            }
            this.debugDisplay.setLength();
        }
    }
    
    @Nullable
    public static RoleDebugDisplay create(@Nonnull final EnumSet<RoleDebugFlags> debugFlags) {
        final boolean debugDisplayState = debugFlags.contains(RoleDebugFlags.DisplayState);
        final boolean debugDisplayTime = debugFlags.contains(RoleDebugFlags.DisplayTime);
        final boolean debugDisplayFlock = debugFlags.contains(RoleDebugFlags.DisplayFlock);
        final boolean debugDisplayAnim = debugFlags.contains(RoleDebugFlags.DisplayAnim);
        final boolean debugDisplayLockedTarget = debugFlags.contains(RoleDebugFlags.DisplayTarget);
        final boolean debugDisplayLightLevel = debugFlags.contains(RoleDebugFlags.DisplayLightLevel);
        final boolean debugDisplayCustom = debugFlags.contains(RoleDebugFlags.DisplayCustom);
        final boolean debugDisplayFreeSlots = debugFlags.contains(RoleDebugFlags.DisplayFreeSlots);
        final boolean debugDisplayPathFinder = debugFlags.contains(RoleDebugFlags.Pathfinder);
        final boolean debugDisplayHP = debugFlags.contains(RoleDebugFlags.DisplayHP);
        final boolean debugDisplayStamina = debugFlags.contains(RoleDebugFlags.DisplayStamina);
        final boolean debugDisplaySpeed = debugFlags.contains(RoleDebugFlags.DisplaySpeed);
        final boolean debugDisplayName = debugFlags.contains(RoleDebugFlags.DisplayName);
        final boolean debugDisplayInternalId = debugFlags.contains(RoleDebugFlags.DisplayInternalId);
        if (!debugDisplayInternalId && !debugDisplayState && !debugDisplayFlock && !debugDisplayTime && !debugDisplayAnim && !debugDisplayLockedTarget && !debugDisplayLightLevel && !debugDisplayCustom && !debugDisplayFreeSlots && !debugDisplayPathFinder && !debugDisplayHP && !debugDisplaySpeed && !debugDisplayName && !debugDisplayStamina) {
            return null;
        }
        final RoleDebugDisplay debugDisplay = new RoleDebugDisplay();
        debugDisplay.debugDisplayState = debugDisplayState;
        debugDisplay.debugDisplayTime = debugDisplayTime;
        debugDisplay.debugDisplayFlock = debugDisplayFlock;
        debugDisplay.debugDisplayAnim = debugDisplayAnim;
        debugDisplay.debugDisplayLockedTarget = debugDisplayLockedTarget;
        debugDisplay.debugDisplayLightLevel = debugDisplayLightLevel;
        debugDisplay.debugDisplayCustom = debugDisplayCustom;
        debugDisplay.debugDisplayFreeSlots = debugDisplayFreeSlots;
        debugDisplay.debugDisplayPathFinder = debugDisplayPathFinder;
        debugDisplay.debugDisplayHP = debugDisplayHP;
        debugDisplay.debugDisplayStamina = debugDisplayStamina;
        debugDisplay.debugDisplaySpeed = debugDisplaySpeed;
        debugDisplay.debugDisplayInternalId = debugDisplayInternalId;
        debugDisplay.debugDisplayName = debugDisplayName;
        return debugDisplay;
    }
}
