package com.xxx.amp.magenta.livecodebench;

import com.xxx.amp.magenta.livecodebench.model.TestRun;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.json.JSONObject;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

public class Runner {
    public static final int STATUS_INTERNAL_ERROR = 255;

    public static void main(String[] args) {
        if (args.length < 3) {
            System.err.println("usage: Runner <test file> <result file> <test timeout in sec>");
            System.err.println("example: Runner question1.json results1.json");
            System.exit(255);
        }

        try {
            Runner runner = new Runner(
                    args[0]
            );
            runner.run(Integer.parseInt(args[2]) * 1000);
            runner.save(args[1]);
        } catch (Throwable e) {
            e.printStackTrace();
            System.exit(STATUS_INTERNAL_ERROR);
        }
    }

    public List<TestRun> run(long testTimeoutMills) throws Throwable {
        this.suite.load(this.testData);
        this.results = this.suite.run(testTimeoutMills);
        return this.results;
    }

    public void save(String resultFile) throws IOException {
        String json = new ObjectMapper().writeValueAsString(this.results);
        Files.writeString(Path.of(resultFile), json);
    }
    private final ProblemTestSuite suite;
    private final String className;
    private final JSONObject testData;
    private List<TestRun> results;

    public Runner(String dataPath) throws IOException, ClassNotFoundException {
        String content = Files.readString(Path.of(dataPath));
        JSONObject data = new JSONObject(content);

        this.className = data.getString("class");
        Class<?> clazz = Thread.currentThread()
                .getContextClassLoader()
                .loadClass(this.className);

        this.testData = new JSONObject(data.getString("input_output"));

        String funcName = null;
        if (this.testData.has("fn_name") && this.testData.get("fn_name") != JSONObject.NULL) {
            funcName = this.testData.getString("fn_name");
        }

        if (funcName != null && !funcName.trim()
                .isEmpty()) {
            this.suite = new FuncCallSuite(clazz);
        } else {
            this.suite = new StdioSuite(clazz);
        }
    }

    public List<TestRun> getResults() {
        return results;
    }

    public ProblemTestSuite getSuite() {
        return suite;
    }

    public String getClassName() {
        return className;
    }

    public JSONObject getTestData() {
        return testData;
    }
}