/*
 * Copyright 2024-2026 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.cloud.ai.graph.node.code.java;

import com.alibaba.cloud.ai.graph.node.code.TemplateTransformer;
import com.alibaba.cloud.ai.graph.node.code.entity.CodeStyle;

/**
 * Java code template transformer Used to convert user code into executable Java programs
 * user method should be {@code public static Object run([..args])}
 *
 * @author HeYQ
 * @since 2024-06-01
 */
public class JavaTemplateTransformer extends TemplateTransformer {

	@Override
	public String getRunnerScript(CodeStyle style) {
		return switch (style) {
			case EXPLICIT_PARAMETERS -> String.format(
					"""
							import java.util.*;
							import com.fasterxml.jackson.databind.ObjectMapper;
							import com.fasterxml.jackson.databind.node.ObjectNode;
							import com.fasterxml.jackson.core.type.TypeReference;
							import java.lang.reflect.Method;

							class Main {
							    public static void main(String[] args) throws Exception {
							        // Parse input parameters
							        String inputsBase64 = "%s";
							        String inputsJson = new String(Base64.getDecoder().decode(inputsBase64));
							        ObjectMapper mapper = new ObjectMapper();
							        Map<String, Object> inputs = mapper.readValue(inputsJson, new TypeReference<>(){});

							        // Execute user code
							        Object result = invokeMethod(Main.class, "run", inputs);

							        // Output results
							        String output = mapper.writeValueAsString(result);
							        System.out.println("%s" + output + "%s");
							    }

							    public static Object invokeMethod(Class<?> clazz, String methodName, Map<String, Object> args)
							        throws Exception {
							        Method func = Arrays.stream(clazz.getMethods()).filter(method -> method.getName().equals(methodName))
							                .filter(method -> method.getParameterCount() == args.size())
							                .findFirst()
							                .orElseThrow();
							        Object[] params = Arrays.stream(func.getParameters()).map(
							                parameter -> args.get(parameter.getName())
							        ).toArray();
							        return func.invoke(null, params);
							    }

							    // user code
							    %s
							}
							""",
					INPUTS_PLACEHOLDER, RESULT_TAG, RESULT_TAG, CODE_PLACEHOLDER);
			case GLOBAL_DICTIONARY -> String.format("""
					import java.util.*;
					import com.fasterxml.jackson.databind.ObjectMapper;
					import com.fasterxml.jackson.databind.node.ObjectNode;
					import com.fasterxml.jackson.core.type.TypeReference;

					class Main {

					    private static final Map<String, Object> params;

					    private static final ObjectMapper mapper;

					    static {
					        try {
					            // Parse input parameters
					            String inputsBase64 = "%s";
					            String inputsJson = new String(Base64.getDecoder().decode(inputsBase64));
					            mapper = new ObjectMapper();
					            params = mapper.readValue(inputsJson, new TypeReference<>(){});
					        } catch (Exception e) {
					            throw new RuntimeException(e);
					        }
					    }

					    public static void main(String[] args) throws Exception {
					        // Execute user code
					        Object result = run();

					        // Output results
					        String output = mapper.writeValueAsString(result);
					        System.out.println("%s" + output + "%s");
					    }

					    // user code
					    %s
					}
					""", INPUTS_PLACEHOLDER, RESULT_TAG, RESULT_TAG, CODE_PLACEHOLDER);
		};
	}

}
