package io.quarkiverse.openapi.generator.deployment.template;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

import io.quarkus.qute.EvalContext;
import io.quarkus.qute.NamespaceResolver;

/**
 * Namespace resolver to mimic the function of io.quarkus.qute.runtime.extensions.StringTemplateExtensions.
 * This extension is built-in with Qute when used in a context with Quarkus DI.
 * Since these extensions are built in build time by Qute we can't use them because our process also runs in build time without
 * a CDI context.
 * So any namespace resolver auto-generated by Quarkus won't be added to our engine.
 *
 * @see <a href="https://quarkus.io/guides/qute-reference#template_extension_methods">Template Extension Methods</a>
 */
public class StrNamespaceResolver implements NamespaceResolver {

    static final StrNamespaceResolver INSTANCE = new StrNamespaceResolver();

    private StrNamespaceResolver() {
    }

    @Override
    public String getNamespace() {
        return "str";
    }

    /**
     * @see io.quarkus.qute.runtime.extensions.StringTemplateExtensions#fmt(String, String, Object...)
     */
    public String fmt(String format, Object... args) {
        return String.format(format, args);
    }

    @Override
    public CompletionStage<Object> resolve(EvalContext context) {
        switch (context.getName()) {
            case "fmt":
                if (context.getParams().size() < 2) {
                    throw new IllegalArgumentException(
                            "Missing required parameter for 'fmt'. Make sure that the function has at least two parameters");
                }
                try {
                    return CompletableFuture.completedFuture(
                            fmt(ExprEvaluator.evaluate(context, context.getParams().get(0)),
                                    ExprEvaluator.evaluate(context, context.getParams().subList(1, context.getParams().size()),
                                            Object.class)));
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            default:
                throw new IllegalArgumentException("There's no method named '" + context.getName() + "'");
        }
    }

}
