/**
 * Copyright © 2012-2021 by Data Virtuality GmbH
 */
package org.teiid.query.scripts.python;

import org.graalvm.polyglot.Context;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import java.util.Arrays;
import java.util.List;

import org.teiid.query.QueryPlugin;

/**
 * @author Nicolas Golovan
 * @date 2021.09.05
 */
public class PythonScriptEngineFactory implements ScriptEngineFactory {

    public PythonScriptEngineFactory() {
    }

    @Override
    public String getEngineName() {
        return "python";
    }

    @Override
    public String getEngineVersion() {
        return query("PYTHON_ENGINE_VERSION");
    }

    @Override
    public List<String> getExtensions() {
        return Arrays.asList(".py");
    }

    @Override
    public List<String> getMimeTypes() {
        return Arrays.asList("application/x-python");
    }

    @Override
    public List<String> getNames() {
        return Arrays.asList("python", "trufflePython", "TrufflePython");
    }

    @Override
    public String getLanguageName() {
        return "python";
    }

    @Override
    public String getLanguageVersion() {
        return query("PYTHON_VERSION");
    }

    @Override
    public Object getParameter(String key) {
        switch (key) {
            case ScriptEngine.NAME:
                return "python";
            case ScriptEngine.ENGINE:
                return getEngineName();
            case ScriptEngine.ENGINE_VERSION:
                return getEngineVersion();
            case ScriptEngine.LANGUAGE:
                return getLanguageName();
            case ScriptEngine.LANGUAGE_VERSION:
                return getLanguageVersion();
            default:
                throw new IllegalArgumentException(QueryPlugin.Util.gs(QueryPlugin.Event.DVCORE301240));
        }
    }

    @Override
    public String getMethodCallSyntax(String object, String method, String... args) {
        final StringBuilder builder = new StringBuilder().append(object).append('.').append(method).append('(');

        final int length = args.length;

        if (length > 0) {
            builder.append(args[0]);
        }

        for (int i = 1; i < length; i++) {
            builder.append(',').append(args[i]);
        }

        builder.append(')');

        return builder.toString();
    }

    @Override
    public String getOutputStatement(String toDisplay) {
        return String.format("print(%s)", toDisplay);
    }

    @Override
    public String getProgram(String... statements) {
        return String.join("\n", statements);
    }

    @Override
    public ScriptEngine getScriptEngine() {
        return new PythonScriptEngine(this);
    }

    private String query(String expression) {
        try (Context context = Context.create("python")) {
            return context.eval("python", expression).asString();
        }
    }

}
