package top.r3944realms.lib39.util.resolve;

import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.entity.EntityType;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39;

import java.util.ArrayList;
import java.util.List;

/**
 * The type Entity list resolve.
 */
public abstract class EntityListResolve {
    /**
     * The Result.
     */
    protected EntityListResolve.EntityResolveResult result;

    /**
     * The type Entity resolve result.
     */
    public static class EntityResolveResult {
        /**
         * The Entity list.
         */
        protected final List<String> entityList = new ArrayList<>();
        /**
         * The Tag list.
         */
        protected final List<String> tagList = new ArrayList<>();
        /**
         * The Mod list.
         */
        protected final List<String> modList = new ArrayList<>();

        /**
         * The enum Type.
         */
        public enum Type {
            /**
             * Entity type.
             */
            ENTITY,
            /**
             * Tag type.
             */
            TAG,
            /**
             * Mod type.
             */
            MOD
        }

        /**
         * Gets map.
         *
         * @param type the type
         * @return the map
         */
        public List<String> getMap(@NotNull Type type) {
            return switch (type) {
                case ENTITY -> entityList;
                case TAG -> tagList;
                case MOD -> modList;
            };
        }

        /**
         * Update.
         *
         * @param entity the entity
         * @param tag    the tag
         * @param mod    the mod
         */
        public void update(List<String> entity, List<String> tag, List<String> mod) {
            entityList.clear();
            entityList.addAll(entity);
            tagList.clear();
            tagList.addAll(tag);
            modList.clear();
            modList.addAll(mod);
        }
    }

    /**
     * Resolve entity resolve result.
     *
     * @param configs the configs
     * @return the entity resolve result
     */
    public EntityResolveResult resolve(@NotNull List<String> configs) {
        List<String> entityList = new ArrayList<>();
        List<String> tagList = new ArrayList<>();
        List<String> modList = new ArrayList<>();
        for (String config : configs) {
            if (!isMatch(config)) continue;

            try {
                String[] entities = resolveEntities(config);
                for (String e : entities) {
                    String trimmed = e.trim();
                    if (trimmed.equals("*")) modList.add("*");
                    else if (trimmed.startsWith("#")) {
                        String body = trimmed.substring(1).trim();
                        if (body.contains(":")) tagList.add(body);
                        else modList.add(body);
                    } else entityList.add(trimmed);
                }
                result.update(entityList, tagList, modList);
            } catch (NumberFormatException ex) {
                Lib39.LOGGER.error("Invalid offset config: {}", config);
            }
        }
        return result;
    }

    /**
     * Is match boolean.
     *
     * @param input the input
     * @return the boolean
     */
    protected abstract boolean isMatch(String input);

    /**
     * Resolve entities string [ ].
     *
     * @param input the input
     * @return the string [ ]
     */
    protected abstract String[] resolveEntities(String input);

    /**
     * Is entity in list boolean.
     *
     * @param type the type
     * @return the boolean
     */
    @SuppressWarnings("deprecation")
    public boolean isEntityInList(EntityType<?> type) {
        String entityId  =  type.builtInRegistryHolder().key().location().toString();
        String modId = entityId.split(":")[0];
        for (String rs : result.entityList) {
            if (rs.equals(entityId)) return true;
        }
        for(String rs : result.tagList) {
            String body = rs.substring(1);
            ResourceLocation tagId = Lib39.rl(body);
            TagKey<EntityType<?>> tag = TagKey.create(Registries.ENTITY_TYPE, tagId);
            if (type.builtInRegistryHolder().is(tag)) return true;
        }
        for(String rs : result.modList) {
            String body = rs.substring(1);
            if (!body.contains(":") && body.equals(modId)) return true;
        }
        return false;
    }
}
