#include "actions.hpp"
#include "json.hpp"
#include "rpc_server.hpp"
#include "vm.hpp"
#include "vm_provider.hpp"
#include <cstdint>
#include <format>
#include <fstream>
#include <string>
#include <vector>

bool print_stack_debug = false;

int execute_file_and_exit(std::string filename)
{
    auto file = std::ifstream();
    file.open(filename.c_str());
    if (!file) {
        std::cout << std::format("error: could not open file '{}'\n", filename);
        return 1;
    }
    auto text = std::string(std::istreambuf_iterator<char> { file }, {});
    auto parsed = sliger::json::parse_json(text);
    if (not parsed.ok()) {
        std::cout << std::format("error: {} at {}:{}\n", parsed.err().msg,
            parsed.err().pos.line, parsed.err().pos.col);
        return 1;
    }
    auto program = std::vector<uint32_t>();
    for (auto& v : parsed.val()->as<sliger::json::Array>().values) {
        program.push_back(
            static_cast<uint32_t>(v->as<sliger::json::Number>().value));
    }
    auto vm = sliger::VM(program,
        {
            .flame_graph = false,
            .code_coverage = false,
            .print_stack_debug = print_stack_debug,
        });
    vm.run_until_done();
    return 0;
}

int main(int argc, char** argv)
{
    if (argc >= 3 && std::string(argv[1]) == "run") {
        return execute_file_and_exit(argv[2]);
    }

    auto state = sliger::rpc::vm_provider::VmProvider();

    auto rpc = sliger::rpc::RpcServer(
        [&](std::unique_ptr<sliger::json::Value> req,
            std::unique_ptr<sliger::rpc::BufferedWriter> writer) {
            auto action = sliger::rpc::action::action_from_json(std::move(req));
            action->perform_action(std::move(writer), state);
        });

    std::cout << "binding on 127.0.0.1:13370\n";
    auto res = rpc.listen();
    if (!res.is_ok()) {
        std::cout << res.err().msg << "\n";
    }
}