package pokefenn.totemic.advancements.criterion;

import java.util.*;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;

import net.minecraft.advancements.ICriterionTrigger;
import net.minecraft.advancements.PlayerAdvancements;
import net.minecraft.advancements.critereon.AbstractCriterionInstance;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.ResourceLocation;
import pokefenn.totemic.Totemic;
import pokefenn.totemic.api.ceremony.Ceremony;

public class CeremonyTrigger implements ICriterionTrigger<CeremonyTrigger.Instance>
{
    private static final ResourceLocation ID = new ResourceLocation(Totemic.MOD_ID, "perform_ceremony");

    private final Map<PlayerAdvancements, CeremonyTrigger.Listeners> listeners = new HashMap<>();

    @Override
    public ResourceLocation getId()
    {
        return ID;
    }

    @Override
    public void addListener(PlayerAdvancements advancements, Listener<Instance> listener)
    {
        Listeners ls = listeners.get(advancements);
        if(ls == null)
        {
            ls = new Listeners(advancements);
            listeners.put(advancements, ls);
        }
        ls.add(listener);
    }

    @Override
    public void removeListener(PlayerAdvancements advancements, Listener<Instance> listener)
    {
        Listeners ls = listeners.get(advancements);
        if(ls != null)
        {
            ls.remove(listener);
            if(ls.isEmpty())
                listeners.remove(advancements);
        }
    }

    @Override
    public void removeAllListeners(PlayerAdvancements advancements)
    {
        listeners.remove(advancements);
    }

    @Override
    public Instance deserializeInstance(JsonObject json, JsonDeserializationContext context)
    {
        String name = JsonUtils.getString(json, "ceremony");
        Ceremony ceremony = Totemic.api.registry().getCeremony(name);
        if(ceremony == null)
            throw new JsonSyntaxException("Unknown ceremony: '" + name + "'");
        else
            return new Instance(ceremony);
    }

    public void trigger(EntityPlayerMP player, Ceremony ceremony)
    {
        Listeners ls = listeners.get(player.getAdvancements());
        if(ls != null)
            ls.trigger(ceremony);
    }

    static class Instance extends AbstractCriterionInstance
    {
        private final Ceremony ceremony;

        Instance(Ceremony ceremony)
        {
            super(ID);
            this.ceremony = ceremony;
        }

        boolean test(Ceremony ceremony)
        {
            return this.ceremony == ceremony;
        }
    }

    static class Listeners
    {
        private final PlayerAdvancements playerAdvancements;
        private final Set<ICriterionTrigger.Listener<CeremonyTrigger.Instance>> listeners = new HashSet<>();

        public Listeners(PlayerAdvancements playerAdvancements)
        {
            this.playerAdvancements = playerAdvancements;
        }

        public boolean isEmpty()
        {
            return listeners.isEmpty();
        }

        public void add(ICriterionTrigger.Listener<CeremonyTrigger.Instance> listener)
        {
            listeners.add(listener);
        }

        public void remove(ICriterionTrigger.Listener<CeremonyTrigger.Instance> listener)
        {
            listeners.remove(listener);
        }

        public void trigger(Ceremony ceremony)
        {
            List<ICriterionTrigger.Listener<CeremonyTrigger.Instance>> passed = null;

            for(ICriterionTrigger.Listener<CeremonyTrigger.Instance> listener: listeners)
            {
                if(listener.getCriterionInstance().test(ceremony))
                {
                    if(passed == null)
                        passed = new ArrayList<>();
                    passed.add(listener);
                }
            }

            if (passed != null)
            {
                for(ICriterionTrigger.Listener<CeremonyTrigger.Instance> listener: passed)
                {
                    listener.grantCriterion(playerAdvancements);
                }
            }
        }
    }
}

@@ -64,9 +64,85 @@
 til.
-*
+HashMap;%0Aimport java.util.HashSet;%0Aimport java.util.Map;%0Aimport java.util.Set
 ;%0A%0Ai
@@ -896,32 +896,16 @@
 ements, 
-CeremonyTrigger.
 Listener
@@ -1141,196 +1141,63 @@
     
-Listeners ls = listeners.get(advancements);%0A        if(ls == null)%0A        %7B%0A            ls = new Listeners(advancements);%0A            listeners.put(advancements, ls);%0A        %7D%0A        ls
+listeners.computeIfAbsent(advancements, Listeners::new)
 .add
@@ -2753,51 +2753,17 @@
 Set%3C
-ICriterionTrigger.Listener%3CCeremonyTrigger.
+Listener%3C
 Inst
@@ -3064,51 +3064,17 @@
 add(
-ICriterionTrigger.Listener%3CCeremonyTrigger.
+Listener%3C
 Inst
@@ -3178,51 +3178,17 @@
 ove(
-ICriterionTrigger.Listener%3CCeremonyTrigger.
+Listener%3C
 Inst
@@ -3337,612 +3337,147 @@
     
-List%3CICriterionTrigger.Listener%3CCeremonyTrigger.Instance%3E%3E passed = null;%0A%0A            for(ICriterionTrigger.Listener%3CCeremonyTrigger.Instance%3E listener: listeners)%0A            %7B%0A                if(listener.getCriterionInstance().test(ceremony))%0A                %7B%0A                    if(passed == null)%0A                        passed = new ArrayList%3C%3E();%0A                    passed.add(listener);%0A                %7D%0A            %7D%0A%0A            if (passed != null)%0A            %7B%0A                for(ICriterionTrigger.Listener%3CCeremonyTrigger.Instance%3E listener: passed)%0A                %7B%0A                   
+listeners.stream()%0A                .filter(listener -%3E listener.getCriterionInstance().test(ceremony))%0A                .forEach(listener -%3E
  lis
@@ -3520,41 +3520,10 @@
 nts)
+)
 ;
-%0A                %7D%0A            %7D
 %0A   

Clean up CeremonyTrigger using Java 8