package info.u_team.u_team_core.data;

import java.io.IOException;
import java.nio.file.Path;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import com.google.common.collect.Maps;
import com.google.gson.JsonObject;

import net.minecraft.data.DirectoryCache;
import net.minecraft.tags.*;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.registries.*;

public abstract class CommonTagsProvider<T extends IForgeRegistryEntry<T>> extends CommonProvider {
	
	protected final IForgeRegistry<T> registry;
	protected final Map<Tag<T>, Tag.Builder<T>> tagToBuilder = Maps.newLinkedHashMap();
	
	public CommonTagsProvider(GenerationData data, IForgeRegistry<T> registry) {
		super(data);
		this.registry = registry;
	}
	
	protected abstract void registerTags();
	
	@Override
	public void act(DirectoryCache cache) {
		tagToBuilder.clear();
		registerTags();
		
		final TagCollection<T> collection = new TagCollection<>(id -> Optional.empty(), "", false, "generated");
		final Map<ResourceLocation, Tag.Builder<T>> map = tagToBuilder.entrySet().stream().collect(Collectors.toMap(entry -> entry.getKey().getId(), Entry::getValue));
		
		collection.registerAll(map);
		collection.getTagMap().forEach((location, tag) -> {
			final JsonObject object = tag.serialize(registry::getKey);
			final Path path = makePath(location);
			try {
				write(cache, object, path);
			} catch (final IOException ex) {
				LOGGER.error(marker, "Could not write data.", ex);
			}
			
		});
		setCollection(collection);
	}
	
	protected abstract void setCollection(TagCollection<T> collection);
	
	protected abstract Path makePath(ResourceLocation location);
	
	protected Tag.Builder<T> getBuilder(Tag<T> tag) {
		final Optional<Tag.Builder<T>> optional = tagToBuilder.entrySet().stream().filter(entry -> entry.getKey().getId().equals(tag.getId())).findAny().map(Entry::getValue);
		if (optional.isPresent()) {
			return optional.get();
		} else {
			return tagToBuilder.computeIfAbsent(tag, otherTag -> Tag.Builder.create());
		}
	}
}
@@ -273,30 +273,17 @@
 ft.data.
-DirectoryCache
+*
 ;%0Aimport
@@ -562,16 +562,27 @@
 Map%3C
-Tag%3CT%3E
+ResourceLocation
 , 
+I
 Tag.
@@ -588,19 +588,16 @@
 .Builder
-%3CT%3E
 %3E tagToB
@@ -904,422 +904,522 @@
 %09%0A%09%09
-final TagCollection%3CT%3E collection = new TagCollection%3C%3E(id -%3E Optional.empty(), %22%22, false, %22generated%22);%0A%09%09final Map%3CResourceLocation, Tag.Builder%3CT%3E%3E map = tagToBuilder.entrySet().stream().collect(Collectors.toMap(entry -%3E entry.getKey().getId(), Entry::getValue));
+tagToBuilder.forEach((location, builder) -%3E %7B%0A%09%09%09final List%3CITag.Proxy%3E list = builder.func_232963_b_(id -%3E tagToBuilder.containsKey(id) ? Tag.func_241284_a_() : null, id -%3E registry.getValue(id)).collect(Collectors.toList());%0A%09%09%09if (!list.isEmpty()) %7B
 %0A%09%09
-%0A
 %09%09
-collection.registerAll(map);%0A%09%09collection.getTagMap().forEach((location, tag) -%3E %7B%0A%09%09%09final JsonObject object = tag.serialize(registry::getKey
+throw new IllegalArgumentException(String.format(%22Couldn't define tag %25s as it is missing following references: %25s%22, location, list.stream().map(Objects::toString).collect(Collectors.joining(%22,%22))));%0A%09%09%09%7D%0A%09%09%09final JsonObject object = builder.func_232965_c_(
 );%0A%09
@@ -1599,50 +1599,81 @@
 %09%09%7D%0A
-%09%09%09%0A
 %09%09%7D);%0A%09
-%09setCollection(collec
+%7D%0A%09%0A%09protected abstract Path makePath(ResourceLocation loca
 tion);%0A
-%09%7D%0A
 %09%0A%09p
@@ -1685,129 +1685,424 @@
 ted 
-abstract void setCollection(TagCollection%3CT%3E collection);%0A%09%0A%09protected abstract Path makePath(ResourceLocation location);
+TagsProvider.Builder%3CT%3E func_240522_a_(ITag.INamedTag%3CT%3E p_240522_1_) %7B%0A%09%09ITag.Builder itag$builder = this.func_240525_b_(p_240522_1_);%0A%09%09return new TagsProvider.Builder%3C%3E(itag$builder, this.registry, modid);%0A%09%7D%0A%09%0A%09protected ITag.Builder func_240525_b_(ITag.INamedTag%3CT%3E p_240525_1_) %7B%0A%09%09return this.tagToBuilder.computeIfAbsent(p_240525_1_.func_230234_a_(), (p_240526_0_) -%3E %7B%0A%09%09%09return new ITag.Builder();%0A%09%09%7D);%0A%09%7D
 %0A%09%0A%09

Update the act method in common Tags provider to work hopefully :)