package top.r3944realms.lib39.api.callback;

import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.resources.Identifier;
import top.r3944realms.lib39.core.command.ICommandHelpManager;
import top.r3944realms.lib39.core.command.model.CommandNode;
import top.r3944realms.lib39.core.command.model.CommandPath;
import top.r3944realms.lib39.core.command.model.Parameter;

/**
 * The interface Register command help callback.
 */
@FunctionalInterface
public interface RegisterCommandHelpCallback {
    /**
     * Register action result.
     *
     * @param registrar the registrar
     * @return the action result
     */
    ActionResult register(RegisterCommandHelpCallback.Registrar registrar);

    /**
     * 创建 Event 实例
     */
    Event<RegisterCommandHelpCallback> EVENT = EventFactory.createArrayBacked(
            RegisterCommandHelpCallback.class,
            (listeners) -> (registrar) -> {
                for (RegisterCommandHelpCallback listener : listeners) {
                    ActionResult result = listener.register(registrar);
                    if (result != ActionResult.PASS) {
                        return result;
                    }
                }
                return ActionResult.PASS;
            }
    );

    /**
     * The interface Registrar.
     */
    interface Registrar {
        /**
         * Gets id.
         *
         * @return the id
         */
        Identifier getID();

        /**
         * Add child.
         *
         * @param child the child
         */
        void addChild(LiteralArgumentBuilder<CommandSourceStack> child);

        /**
         * Get context command build context.
         *
         * @return the command build context
         */
        CommandBuildContext getContext();

        /**
         * Get tree literal argument builder.
         *
         * @return the literal argument builder
         */
        LiteralArgumentBuilder<CommandSourceStack> getTree();

        /**
         * 注册命令帮助信息
         *
         * @param CommandNode 命令节点
         * @param description 命令描述
         */
        void registerHelp(CommandNode CommandNode, MutableComponent description);

        /**
         * 注册命令帮助信息
         *
         * @param CommandNode    命令节点
         * @param descriptionKey 命令描述的语言键
         */
        void registerHelp(CommandNode CommandNode, String descriptionKey);

        /**
         * 注册命令参数
         *
         * @param commandPath       命令节点
         * @param parametersBuilder 参数列表构造器
         */
        void registerParameters(CommandPath commandPath, Parameter.Builder parametersBuilder);
    }

    /**
     * The type Command help registrar.
     */
    record CommandHelpRegistrar(LiteralArgumentBuilder<CommandSourceStack> builder, ICommandHelpManager helpManager, CommandBuildContext context) implements Registrar {
        @Override
        public Identifier getID() {
            return helpManager.getID();
        }

        @Override
        public void addChild(LiteralArgumentBuilder<CommandSourceStack> child) {
            this.builder.then(child);
        }

        @Override
        public CommandBuildContext getContext(){
            return this.context;
        }

        @Override
        public LiteralArgumentBuilder<CommandSourceStack> getTree(){
            return this.builder;
        }

        @Override
        public void registerHelp(CommandNode CommandNode, MutableComponent description) {
            this.helpManager.registerCommandHelp(CommandNode, description);
        }

        @Override
        public void registerHelp(CommandNode CommandNode, String descriptionKey) {
            this.helpManager.registerCommandHelp(CommandNode, descriptionKey);
        }

        @Override
        public void registerParameters(CommandPath commandPath, Parameter.Builder parametersBuilder) {
            this.helpManager.registerCommandParameters(commandPath, parametersBuilder);
        }
    }
}
