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.HashMap;
import java.util.List;
import java.util.Map;

/**
 * The type Entity map resolve.
 *
 * @param <T> the type parameter
 */
public abstract class EntityMapResolve<T> {
    /**
     * The Result.
     */
    protected EntityResolveResult<T> result;

    /**
     * The type Entity resolve result.
     *
     * @param <T> the type parameter
     */
    public static class EntityResolveResult<T> {
        /**
         * The Entity map.
         */
        protected final Map<String, T> entityMap = new HashMap<>();
        /**
         * The Tag map.
         */
        protected final Map<String, T> tagMap = new HashMap<>();
        /**
         * The Mod map.
         */
        protected final Map<String, T> modMap = new HashMap<>();

        /**
         * 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 Map<String, T> getMap(@NotNull Type type) {
            return switch (type) {
                case ENTITY -> entityMap;
                case TAG -> tagMap;
                case MOD -> modMap;
            };
        }

        /**
         * Update.
         *
         * @param entity the entity
         * @param tag    the tag
         * @param mod    the mod
         */
        public void update(Map<String, T> entity, Map<String, T> tag, Map<String, T> mod) {
            entityMap.clear();
            entityMap.putAll(entity);
            tagMap.clear();
            tagMap.putAll(tag);
            modMap.clear();
            modMap.putAll(mod);
        }
    }

    /**
     * Resolve entity resolve result.
     *
     * @param configs the configs
     * @return the entity resolve result
     */
    public EntityResolveResult<T> resolve(@NotNull List<String> configs) {
        Map<String, T> entityMap = new HashMap<>();
        Map<String, T> tagMap = new HashMap<>();
        Map<String, T> modMap = new HashMap<>();

        for (String config : configs) {
            if (!isMatch(config)) continue;

            try {
                T t = resolveT(config);

                String[] entities = resolveEntities(config);
                for (String e : entities) {
                    String trimmed = e.trim();
                    if (trimmed.equals("*")) modMap.put("*", t);
                    else if (trimmed.startsWith("#")) {
                        String body = trimmed.substring(1).trim();
                        if (body.contains(":")) tagMap.put(body, t);
                        else modMap.put(body, t);
                    } else entityMap.put(trimmed, t);
                }
                result.update(entityMap, tagMap, modMap);
            } 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 t t.
     *
     * @param input the input
     * @return the t
     */
    protected abstract T resolveT(String input);

    /**
     * Resolve entities string [ ].
     *
     * @param input the input
     * @return the string [ ]
     */
    protected abstract String[] resolveEntities(String input);
    /**
     * 查找实体对应的值，如果找到返回匹配结果，否则返回null
     */
    @SuppressWarnings("deprecation")
    private EntityMatchResult<T> findEntityMatch(EntityType<?> type) {
        String entityId = type.builtInRegistryHolder().key().location().toString();
        String modId = entityId.split(":")[0];

        // 检查实体ID匹配
        for (String rs : result.entityMap.keySet()) {
            if (rs.equals(entityId)) {
                return new EntityMatchResult<>(EntityResolveResult.Type.ENTITY, rs, result.entityMap.get(rs));
            }
        }

        // 检查标签匹配
        for (String rs : result.tagMap.keySet()) {
            String body = rs.startsWith("#") ? rs.substring(1) : rs;
            ResourceLocation tagId = Lib39.rl(body);
            TagKey<EntityType<?>> tag = TagKey.create(Registries.ENTITY_TYPE, tagId);
            if (type.builtInRegistryHolder().is(tag)) {
                return new EntityMatchResult<>(EntityResolveResult.Type.TAG, rs, result.tagMap.get(rs));
            }
        }

        // 检查模组匹配
        for (String rs : result.modMap.keySet()) {
            String body = rs.startsWith("#") ? rs.substring(1) : rs;
            if (!body.contains(":") && body.equals(modId)) {
                return new EntityMatchResult<>(EntityResolveResult.Type.MOD, rs, result.modMap.get(rs));
            }
        }

        return null;
    }

    /**
     * Is entity t in map boolean.
     *
     * @param type the type
     * @return the boolean
     */
    public boolean isEntityTInMap(EntityType<?> type) {
        return findEntityMatch(type) != null;
    }

    /**
     * Gets entity t in map.
     *
     * @param type the type
     * @return the entity t in map
     */
    public T getEntityTInMap(EntityType<?> type) {
        EntityMatchResult<T> match = findEntityMatch(type);
        return match != null ? match.value : null;
    }

    /**
     * 内部类，用于存储实体匹配结果
     */
    private record EntityMatchResult<T>(EntityResolveResult.Type type, String key, T value) {
    }

}
