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

package com.hypixel.hytale.server.core.modules.entity.damage;

import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.server.core.command.system.CommandSender;
import com.hypixel.hytale.server.core.modules.entity.component.DisplayNameComponent;
import java.util.Locale;
import com.hypixel.hytale.server.core.asset.type.particle.config.WorldParticle;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelParticle;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.core.meta.IMetaRegistry;
import com.hypixel.hytale.server.core.meta.DynamicMetaStore;
import com.hypixel.hytale.server.core.meta.IMetaStoreImpl;
import com.hypixel.hytale.server.core.entity.knockback.KnockbackComponent;
import com.hypixel.hytale.math.vector.Vector4d;
import com.hypixel.hytale.server.core.meta.MetaKey;
import com.hypixel.hytale.server.core.meta.MetaRegistry;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.meta.IMetaStore;
import com.hypixel.hytale.component.system.CancellableEcsEvent;

public class Damage extends CancellableEcsEvent implements IMetaStore<Damage>
{
    @Nonnull
    private static final Message MESSAGE_GENERAL_DAMAGE_CAUSE_UNKNOWN;
    @Nonnull
    public static final MetaRegistry<Damage> META_REGISTRY;
    @Nonnull
    public static final MetaKey<Vector4d> HIT_LOCATION;
    @Nonnull
    public static final MetaKey<Float> HIT_ANGLE;
    @Nonnull
    public static final MetaKey<Particles> IMPACT_PARTICLES;
    @Nonnull
    public static final MetaKey<SoundEffect> IMPACT_SOUND_EFFECT;
    @Nonnull
    public static final MetaKey<SoundEffect> PLAYER_IMPACT_SOUND_EFFECT;
    @Nonnull
    public static final MetaKey<CameraEffect> CAMERA_EFFECT;
    @Nonnull
    public static final MetaKey<String> DEATH_ICON;
    @Nonnull
    public static final MetaKey<Boolean> BLOCKED;
    @Nonnull
    public static final MetaKey<Float> STAMINA_DRAIN_MULTIPLIER;
    @Nonnull
    public static final MetaKey<Boolean> CAN_BE_PREDICTED;
    @Nonnull
    public static final MetaKey<KnockbackComponent> KNOCKBACK_COMPONENT;
    @Nonnull
    public static final Source NULL_SOURCE;
    @Nonnull
    private final IMetaStoreImpl<Damage> metaStore;
    private final float initialAmount;
    private int damageCauseIndex;
    @Nonnull
    private Source source;
    private float amount;
    
    public Damage(@Nonnull final Source source, @Nonnull final DamageCause damageCause, final float amount) {
        this.metaStore = new DynamicMetaStore<Damage>(this, Damage.META_REGISTRY);
        this.source = source;
        this.damageCauseIndex = DamageCause.getAssetMap().getIndex(damageCause.getId());
        this.amount = amount;
        this.initialAmount = amount;
    }
    
    public Damage(@Nonnull final Source source, final int damageCauseIndex, final float amount) {
        this.metaStore = new DynamicMetaStore<Damage>(this, Damage.META_REGISTRY);
        this.source = source;
        this.damageCauseIndex = damageCauseIndex;
        this.amount = amount;
        this.initialAmount = amount;
    }
    
    public int getDamageCauseIndex() {
        return this.damageCauseIndex;
    }
    
    public void setDamageCauseIndex(final int damageCauseIndex) {
        this.damageCauseIndex = damageCauseIndex;
    }
    
    @Deprecated
    @Nullable
    public DamageCause getCause() {
        return DamageCause.getAssetMap().getAsset(this.damageCauseIndex);
    }
    
    @Nonnull
    public Source getSource() {
        return this.source;
    }
    
    public void setSource(@Nonnull final Source source) {
        this.source = source;
    }
    
    public float getAmount() {
        return this.amount;
    }
    
    public void setAmount(final float amount) {
        this.amount = amount;
    }
    
    public float getInitialAmount() {
        return this.initialAmount;
    }
    
    @Nonnull
    public Message getDeathMessage(@Nonnull final Ref<EntityStore> targetRef, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        return this.source.getDeathMessage(this, targetRef, componentAccessor);
    }
    
    @Nonnull
    @Override
    public IMetaStoreImpl<Damage> getMetaStore() {
        return this.metaStore;
    }
    
    static {
        MESSAGE_GENERAL_DAMAGE_CAUSE_UNKNOWN = Message.translation("server.general.damageCauses.unknown");
        META_REGISTRY = new MetaRegistry<Damage>();
        HIT_LOCATION = Damage.META_REGISTRY.registerMetaObject();
        HIT_ANGLE = Damage.META_REGISTRY.registerMetaObject();
        IMPACT_PARTICLES = Damage.META_REGISTRY.registerMetaObject();
        IMPACT_SOUND_EFFECT = Damage.META_REGISTRY.registerMetaObject();
        PLAYER_IMPACT_SOUND_EFFECT = Damage.META_REGISTRY.registerMetaObject();
        CAMERA_EFFECT = Damage.META_REGISTRY.registerMetaObject();
        DEATH_ICON = Damage.META_REGISTRY.registerMetaObject();
        BLOCKED = Damage.META_REGISTRY.registerMetaObject(data -> Boolean.FALSE);
        STAMINA_DRAIN_MULTIPLIER = Damage.META_REGISTRY.registerMetaObject();
        CAN_BE_PREDICTED = Damage.META_REGISTRY.registerMetaObject(data -> Boolean.FALSE);
        KNOCKBACK_COMPONENT = Damage.META_REGISTRY.registerMetaObject();
        NULL_SOURCE = new Source() {};
    }
    
    public static class Particles
    {
        @Nullable
        protected ModelParticle[] modelParticles;
        @Nullable
        protected WorldParticle[] worldParticles;
        protected double viewDistance;
        
        public Particles(@Nullable final ModelParticle[] modelParticles, @Nullable final WorldParticle[] worldParticles, final double viewDistance) {
            this.modelParticles = modelParticles;
            this.worldParticles = worldParticles;
            this.viewDistance = viewDistance;
        }
        
        @Nullable
        public ModelParticle[] getModelParticles() {
            return this.modelParticles;
        }
        
        public void setModelParticles(@Nullable final ModelParticle[] modelParticles) {
            this.modelParticles = modelParticles;
        }
        
        @Nullable
        public WorldParticle[] getWorldParticles() {
            return this.worldParticles;
        }
        
        public void setWorldParticles(@Nullable final WorldParticle[] worldParticles) {
            this.worldParticles = worldParticles;
        }
        
        public double getViewDistance() {
            return this.viewDistance;
        }
        
        public void setViewDistance(final double viewDistance) {
            this.viewDistance = viewDistance;
        }
    }
    
    public static class SoundEffect
    {
        private int soundEventIndex;
        
        public SoundEffect(final int soundEventIndex) {
            this.soundEventIndex = soundEventIndex;
        }
        
        public void setSoundEventIndex(final int soundEventIndex) {
            this.soundEventIndex = soundEventIndex;
        }
        
        public int getSoundEventIndex() {
            return this.soundEventIndex;
        }
    }
    
    record CameraEffect(int cameraEffectIndex) {
        public int getEffectIndex() {
            return this.cameraEffectIndex;
        }
    }
    
    public interface Source
    {
        @Nonnull
        default Message getDeathMessage(@Nonnull final Damage info, @Nonnull final Ref<EntityStore> targetRef, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
            final DamageCause damageCauseAsset = DamageCause.getAssetMap().getAsset(info.damageCauseIndex);
            final String causeId = (damageCauseAsset != null) ? damageCauseAsset.getId().toLowerCase(Locale.ROOT) : "unknown";
            final Message damageCauseMessage = Message.translation("server.general.damageCauses." + causeId);
            return Message.translation("server.general.killedBy").param("damageSource", damageCauseMessage);
        }
    }
    
    public static class EnvironmentSource implements Source
    {
        @Nonnull
        private final String type;
        
        public EnvironmentSource(@Nonnull final String type) {
            this.type = type;
        }
        
        @Nonnull
        public String getType() {
            return this.type;
        }
        
        @Nonnull
        @Override
        public Message getDeathMessage(@Nonnull final Damage info, @Nonnull final Ref<EntityStore> targetRef, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
            return Message.translation("server.general.killedBy").param("damageSource", this.type);
        }
    }
    
    public static class EntitySource implements Source
    {
        @Nonnull
        protected final Ref<EntityStore> sourceRef;
        
        public EntitySource(@Nonnull final Ref<EntityStore> sourceRef) {
            this.sourceRef = sourceRef;
        }
        
        @Nonnull
        public Ref<EntityStore> getRef() {
            return this.sourceRef;
        }
        
        @Nonnull
        @Override
        public Message getDeathMessage(@Nonnull final Damage info, @Nonnull final Ref<EntityStore> targetRef, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
            Message damageCauseMessage = Damage.MESSAGE_GENERAL_DAMAGE_CAUSE_UNKNOWN;
            final DisplayNameComponent displayNameComponent = componentAccessor.getComponent(this.sourceRef, DisplayNameComponent.getComponentType());
            if (displayNameComponent != null) {
                final Message displayName = displayNameComponent.getDisplayName();
                if (displayName != null) {
                    damageCauseMessage = displayName;
                }
            }
            return Message.translation("server.general.killedBy").param("damageSource", damageCauseMessage);
        }
    }
    
    public static class ProjectileSource extends EntitySource
    {
        @Nonnull
        protected final Ref<EntityStore> projectile;
        
        public ProjectileSource(@Nonnull final Ref<EntityStore> shooter, @Nonnull final Ref<EntityStore> projectile) {
            super(shooter);
            this.projectile = projectile;
        }
        
        @Nonnull
        public Ref<EntityStore> getProjectile() {
            return this.projectile;
        }
    }
    
    public static class CommandSource implements Source
    {
        @Nonnull
        private static final String COMMAND_NAME_UNKNOWN = "Unknown";
        @Nonnull
        private final CommandSender commandSender;
        @Nullable
        private final String commandName;
        
        public CommandSource(@Nonnull final CommandSender commandSender, @Nonnull final AbstractCommand cmd) {
            this(commandSender, cmd.getName());
        }
        
        public CommandSource(@Nonnull final CommandSender commandSender, @Nullable final String commandName) {
            this.commandSender = commandSender;
            this.commandName = commandName;
        }
        
        @Nonnull
        @Override
        public Message getDeathMessage(@Nonnull final Damage info, @Nonnull final Ref<EntityStore> targetRef, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
            return Message.translation("server.general.killedByCommand").param("displayName", this.commandSender.getDisplayName()).param("commandName", (this.commandName != null) ? this.commandName : "Unknown");
        }
    }
}
