package net.minecraft.world.effect;

import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import java.util.Iterator;
import net.minecraft.world.entity.ai.attributes.AttributeMap;
import java.util.UUID;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.Util;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.LivingEntity;
import com.google.common.collect.Maps;
import net.minecraft.core.Registry;
import javax.annotation.Nullable;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attribute;
import java.util.Map;

public class MobEffect {
    private final Map<Attribute, AttributeModifier> attributeModifiers;
    private final MobEffectCategory category;
    private final int color;
    @Nullable
    private String descriptionId;
    
    @Nullable
    public static MobEffect byId(final int integer) {
        return Registry.MOB_EFFECT.byId(integer);
    }
    
    public static int getId(final MobEffect aoe) {
        return Registry.MOB_EFFECT.getId(aoe);
    }
    
    protected MobEffect(final MobEffectCategory aof, final int integer) {
        this.attributeModifiers = Maps.newHashMap();
        this.category = aof;
        this.color = integer;
    }
    
    public void applyEffectTick(final LivingEntity aoy, final int integer) {
        if (this == MobEffects.REGENERATION) {
            if (aoy.getHealth() < aoy.getMaxHealth()) {
                aoy.heal(1.0f);
            }
        }
        else if (this == MobEffects.POISON) {
            if (aoy.getHealth() > 1.0f) {
                aoy.hurt(DamageSource.MAGIC, 1.0f);
            }
        }
        else if (this == MobEffects.WITHER) {
            aoy.hurt(DamageSource.WITHER, 1.0f);
        }
        else if (this == MobEffects.HUNGER && aoy instanceof Player) {
            ((Player)aoy).causeFoodExhaustion(0.005f * (integer + 1));
        }
        else if (this == MobEffects.SATURATION && aoy instanceof Player) {
            if (!aoy.level.isClientSide) {
                ((Player)aoy).getFoodData().eat(integer + 1, 1.0f);
            }
        }
        else if ((this == MobEffects.HEAL && !aoy.isInvertedHealAndHarm()) || (this == MobEffects.HARM && aoy.isInvertedHealAndHarm())) {
            aoy.heal((float)Math.max(4 << integer, 0));
        }
        else if ((this == MobEffects.HARM && !aoy.isInvertedHealAndHarm()) || (this == MobEffects.HEAL && aoy.isInvertedHealAndHarm())) {
            aoy.hurt(DamageSource.MAGIC, (float)(6 << integer));
        }
    }
    
    public void applyInstantenousEffect(@Nullable final Entity aom1, @Nullable final Entity aom2, final LivingEntity aoy, final int integer, final double double5) {
        if ((this == MobEffects.HEAL && !aoy.isInvertedHealAndHarm()) || (this == MobEffects.HARM && aoy.isInvertedHealAndHarm())) {
            final int integer2 = (int)(double5 * (4 << integer) + 0.5);
            aoy.heal((float)integer2);
        }
        else if ((this == MobEffects.HARM && !aoy.isInvertedHealAndHarm()) || (this == MobEffects.HEAL && aoy.isInvertedHealAndHarm())) {
            final int integer2 = (int)(double5 * (6 << integer) + 0.5);
            if (aom1 == null) {
                aoy.hurt(DamageSource.MAGIC, (float)integer2);
            }
            else {
                aoy.hurt(DamageSource.indirectMagic(aom1, aom2), (float)integer2);
            }
        }
        else {
            this.applyEffectTick(aoy, integer);
        }
    }
    
    public boolean isDurationEffectTick(final int integer1, final int integer2) {
        if (this == MobEffects.REGENERATION) {
            final int integer3 = 50 >> integer2;
            return integer3 <= 0 || integer1 % integer3 == 0;
        }
        if (this == MobEffects.POISON) {
            final int integer3 = 25 >> integer2;
            return integer3 <= 0 || integer1 % integer3 == 0;
        }
        if (this == MobEffects.WITHER) {
            final int integer3 = 40 >> integer2;
            return integer3 <= 0 || integer1 % integer3 == 0;
        }
        return this == MobEffects.HUNGER;
    }
    
    public boolean isInstantenous() {
        return false;
    }
    
    protected String getOrCreateDescriptionId() {
        if (this.descriptionId == null) {
            this.descriptionId = Util.makeDescriptionId("effect", Registry.MOB_EFFECT.getKey(this));
        }
        return this.descriptionId;
    }
    
    public String getDescriptionId() {
        return this.getOrCreateDescriptionId();
    }
    
    public Component getDisplayName() {
        return new TranslatableComponent(this.getDescriptionId());
    }
    
    public MobEffectCategory getCategory() {
        return this.category;
    }
    
    public int getColor() {
        return this.color;
    }
    
    public MobEffect addAttributeModifier(final Attribute aps, final String string, final double double3, final AttributeModifier.Operation a) {
        final AttributeModifier apv7 = new AttributeModifier(UUID.fromString(string), this::getDescriptionId, double3, a);
        this.attributeModifiers.put(aps, apv7);
        return this;
    }
    
    public Map<Attribute, AttributeModifier> getAttributeModifiers() {
        return this.attributeModifiers;
    }
    
    public void removeAttributeModifiers(final LivingEntity aoy, final AttributeMap apu, final int integer) {
        for (final Map.Entry<Attribute, AttributeModifier> entry6 : this.attributeModifiers.entrySet()) {
            final AttributeInstance apt7 = apu.getInstance(entry6.getKey());
            if (apt7 != null) {
                apt7.removeModifier(entry6.getValue());
            }
        }
    }
    
    public void addAttributeModifiers(final LivingEntity aoy, final AttributeMap apu, final int integer) {
        for (final Map.Entry<Attribute, AttributeModifier> entry6 : this.attributeModifiers.entrySet()) {
            final AttributeInstance apt7 = apu.getInstance(entry6.getKey());
            if (apt7 != null) {
                final AttributeModifier apv8 = entry6.getValue();
                apt7.removeModifier(apv8);
                apt7.addPermanentModifier(new AttributeModifier(apv8.getId(), this.getDescriptionId() + " " + integer, this.getAttributeModifierValue(integer, apv8), apv8.getOperation()));
            }
        }
    }
    
    public double getAttributeModifierValue(final int integer, final AttributeModifier apv) {
        return apv.getAmount() * (integer + 1);
    }
    
    public boolean isBeneficial() {
        return this.category == MobEffectCategory.BENEFICIAL;
    }
}
