package net.minecraft.world.effect;

import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import java.util.Iterator;
import net.minecraft.world.entity.ai.attributes.BaseAttributeMap;
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 aki) {
        return Registry.MOB_EFFECT.getId(aki);
    }
    
    protected MobEffect(final MobEffectCategory akj, final int integer) {
        this.attributeModifiers = Maps.newHashMap();
        this.category = akj;
        this.color = integer;
    }
    
    public void applyEffectTick(final LivingEntity akz, final int integer) {
        if (this == MobEffects.REGENERATION) {
            if (akz.getHealth() < akz.getMaxHealth()) {
                akz.heal(1.0f);
            }
        }
        else if (this == MobEffects.POISON) {
            if (akz.getHealth() > 1.0f) {
                akz.hurt(DamageSource.MAGIC, 1.0f);
            }
        }
        else if (this == MobEffects.WITHER) {
            akz.hurt(DamageSource.WITHER, 1.0f);
        }
        else if (this == MobEffects.HUNGER && akz instanceof Player) {
            ((Player)akz).causeFoodExhaustion(0.005f * (integer + 1));
        }
        else if (this == MobEffects.SATURATION && akz instanceof Player) {
            if (!akz.level.isClientSide) {
                ((Player)akz).getFoodData().eat(integer + 1, 1.0f);
            }
        }
        else if ((this == MobEffects.HEAL && !akz.isInvertedHealAndHarm()) || (this == MobEffects.HARM && akz.isInvertedHealAndHarm())) {
            akz.heal((float)Math.max(4 << integer, 0));
        }
        else if ((this == MobEffects.HARM && !akz.isInvertedHealAndHarm()) || (this == MobEffects.HEAL && akz.isInvertedHealAndHarm())) {
            akz.hurt(DamageSource.MAGIC, (float)(6 << integer));
        }
    }
    
    public void applyInstantenousEffect(@Nullable final Entity akq1, @Nullable final Entity akq2, final LivingEntity akz, final int integer, final double double5) {
        if ((this == MobEffects.HEAL && !akz.isInvertedHealAndHarm()) || (this == MobEffects.HARM && akz.isInvertedHealAndHarm())) {
            final int integer2 = (int)(double5 * (4 << integer) + 0.5);
            akz.heal((float)integer2);
        }
        else if ((this == MobEffects.HARM && !akz.isInvertedHealAndHarm()) || (this == MobEffects.HEAL && akz.isInvertedHealAndHarm())) {
            final int integer2 = (int)(double5 * (6 << integer) + 0.5);
            if (akq1 == null) {
                akz.hurt(DamageSource.MAGIC, (float)integer2);
            }
            else {
                akz.hurt(DamageSource.indirectMagic(akq1, akq2), (float)integer2);
            }
        }
        else {
            this.applyEffectTick(akz, 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(), new Object[0]);
    }
    
    public MobEffectCategory getCategory() {
        return this.category;
    }
    
    public int getColor() {
        return this.color;
    }
    
    public MobEffect addAttributeModifier(final Attribute alq, final String string, final double double3, final AttributeModifier.Operation a) {
        final AttributeModifier als7 = new AttributeModifier(UUID.fromString(string), this::getDescriptionId, double3, a);
        this.attributeModifiers.put(alq, als7);
        return this;
    }
    
    public Map<Attribute, AttributeModifier> getAttributeModifiers() {
        return this.attributeModifiers;
    }
    
    public void removeAttributeModifiers(final LivingEntity akz, final BaseAttributeMap alu, final int integer) {
        for (final Map.Entry<Attribute, AttributeModifier> entry6 : this.attributeModifiers.entrySet()) {
            final AttributeInstance alr7 = alu.getInstance(entry6.getKey());
            if (alr7 != null) {
                alr7.removeModifier(entry6.getValue());
            }
        }
    }
    
    public void addAttributeModifiers(final LivingEntity akz, final BaseAttributeMap alu, final int integer) {
        for (final Map.Entry<Attribute, AttributeModifier> entry6 : this.attributeModifiers.entrySet()) {
            final AttributeInstance alr7 = alu.getInstance(entry6.getKey());
            if (alr7 != null) {
                final AttributeModifier als8 = entry6.getValue();
                alr7.removeModifier(als8);
                alr7.addModifier(new AttributeModifier(als8.getId(), this.getDescriptionId() + " " + integer, this.getAttributeModifierValue(integer, als8), als8.getOperation()));
            }
        }
    }
    
    public double getAttributeModifierValue(final int integer, final AttributeModifier als) {
        return als.getAmount() * (integer + 1);
    }
    
    public boolean isBeneficial() {
        return this.category == MobEffectCategory.BENEFICIAL;
    }
}
