package com.shanebeestudios.skbee.elements.registry.expression;

import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.util.Kleenean;
import com.github.shanebeee.skr.Registration;
import com.shanebeestudios.skbee.config.SkBeeMetrics;
import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.tag.TagKey;
import org.bukkit.Keyed;
import org.bukkit.Registry;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

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

@SuppressWarnings({"UnstableApiUsage", "rawtypes"})
public class ExprRegistryTagKeys extends SimpleExpression<TagKey> {

    public static void register(Registration reg) {
        reg.newCombinedExpression(ExprRegistryTagKeys.class, TagKey.class,
                "tag keys (of|from) %registrykey%",
                "%registrykey% tag keys")
            .name("Registry - TagKeys from Registry")
            .description("Get all the tag keys that belong to a registry.")
            .examples("loop tag keys of block registry:",
                "set {_keys::*} to tag keys of biome registry")
            .since("3.8.0")
            .register();
    }

    private Expression<RegistryKey<Keyed>> registryKey;

    @SuppressWarnings("unchecked")
    @Override
    public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
        SkBeeMetrics.Features.REGISTRY.used();
        this.registryKey = (Expression<RegistryKey<Keyed>>) exprs[0];
        return true;
    }

    @Override
    protected TagKey<?> @Nullable [] get(Event event) {
        RegistryKey<Keyed> registryKey = this.registryKey.getSingle(event);
        if (registryKey == null) return null;

        Registry<?> registry = RegistryAccess.registryAccess().getRegistry(registryKey);
        List<TagKey<?>> tagKeys = new ArrayList<>();
        registry.getTags().forEach(tag -> tagKeys.add(tag.tagKey()));
        tagKeys.sort(Comparator.comparing(tagKey -> tagKey.key().toString()));
        return tagKeys.toArray(new TagKey[0]);
    }

    @Override
    public boolean isSingle() {
        return false;
    }

    @Override
    public Class<? extends TagKey> getReturnType() {
        return TagKey.class;
    }

    @Override
    public String toString(Event e, boolean d) {
        return "tag keys of " + this.registryKey.toString(e, d);
    }

}
