package net.minecraft.world.entity.ai.attributes;

import java.util.AbstractList;
import org.apache.logging.log4j.LogManager;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.Util;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.core.Registry;
import java.util.Iterator;
import net.minecraft.nbt.ListTag;
import java.util.function.Consumer;
import com.google.common.collect.Multimap;
import java.util.UUID;
import javax.annotation.Nullable;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.Collection;
import com.google.common.collect.Sets;
import com.google.common.collect.Maps;
import java.util.Set;
import java.util.Map;
import org.apache.logging.log4j.Logger;

public class AttributeMap {
    private static final Logger LOGGER;
    private final Map<Attribute, AttributeInstance> attributes;
    private final Set<AttributeInstance> dirtyAttributes;
    private final AttributeSupplier supplier;
    
    public AttributeMap(final AttributeSupplier apw) {
        this.attributes = Maps.newHashMap();
        this.dirtyAttributes = Sets.newHashSet();
        this.supplier = apw;
    }
    
    private void onAttributeModified(final AttributeInstance apt) {
        if (apt.getAttribute().isClientSyncable()) {
            this.dirtyAttributes.add(apt);
        }
    }
    
    public Set<AttributeInstance> getDirtyAttributes() {
        return this.dirtyAttributes;
    }
    
    public Collection<AttributeInstance> getSyncableAttributes() {
        return this.attributes.values().stream().filter(apt -> apt.getAttribute().isClientSyncable()).collect(Collectors.toList());
    }
    
    @Nullable
    public AttributeInstance getInstance(final Attribute aps) {
        return this.attributes.computeIfAbsent(aps, aps -> this.supplier.createInstance(this::onAttributeModified, aps));
    }
    
    public boolean hasAttribute(final Attribute aps) {
        return this.attributes.get(aps) != null || this.supplier.hasAttribute(aps);
    }
    
    public boolean hasModifier(final Attribute aps, final UUID uUID) {
        final AttributeInstance apt4 = this.attributes.get(aps);
        return (apt4 != null) ? (apt4.getModifier(uUID) != null) : this.supplier.hasModifier(aps, uUID);
    }
    
    public double getValue(final Attribute aps) {
        final AttributeInstance apt3 = this.attributes.get(aps);
        return (apt3 != null) ? apt3.getValue() : this.supplier.getValue(aps);
    }
    
    public double getBaseValue(final Attribute aps) {
        final AttributeInstance apt3 = this.attributes.get(aps);
        return (apt3 != null) ? apt3.getBaseValue() : this.supplier.getBaseValue(aps);
    }
    
    public double getModifierValue(final Attribute aps, final UUID uUID) {
        final AttributeInstance apt4 = this.attributes.get(aps);
        return (apt4 != null) ? apt4.getModifier(uUID).getAmount() : this.supplier.getModifierValue(aps, uUID);
    }
    
    public void removeAttributeModifiers(final Multimap<Attribute, AttributeModifier> multimap) {
        final AttributeInstance apt4;
        multimap.asMap().forEach((aps, collection) -> {
            apt4 = this.attributes.get(aps);
            if (apt4 != null) {
                collection.forEach(apt4::removeModifier);
            }
        });
    }
    
    public void addTransientAttributeModifiers(final Multimap<Attribute, AttributeModifier> multimap) {
        final AttributeInstance apt4;
        multimap.forEach((aps, apv) -> {
            apt4 = this.getInstance(aps);
            if (apt4 != null) {
                apt4.removeModifier(apv);
                apt4.addTransientModifier(apv);
            }
        });
    }
    
    public void assignValues(final AttributeMap apu) {
        final AttributeInstance apt2;
        apu.attributes.values().forEach(apt -> {
            apt2 = this.getInstance(apt.getAttribute());
            if (apt2 != null) {
                apt2.replaceFrom(apt);
            }
        });
    }
    
    public ListTag save() {
        final ListTag lk2 = new ListTag();
        for (final AttributeInstance apt4 : this.attributes.values()) {
            ((AbstractList<CompoundTag>)lk2).add(apt4.save());
        }
        return lk2;
    }
    
    public void load(final ListTag lk) {
        for (int integer3 = 0; integer3 < lk.size(); ++integer3) {
            final CompoundTag le4 = lk.getCompound(integer3);
            final String string5 = le4.getString("Name");
            final AttributeInstance apt4;
            final CompoundTag le5;
            Util.<Attribute>ifElse(Registry.ATTRIBUTE.getOptional(ResourceLocation.tryParse(string5)), aps -> {
                apt4 = this.getInstance(aps);
                if (apt4 != null) {
                    apt4.load(le5);
                }
                return;
            }, () -> AttributeMap.LOGGER.warn("Ignoring unknown attribute '{}'", string5));
        }
    }
    
    static {
        LOGGER = LogManager.getLogger();
    }
}
