
#include <iostream>
#include <fstream>
#include <string>
#include <csignal>
#include <cstdlib>
#include <chrono>

bool running = true;

void signalHandler(int signum) {
    running = false;
    std::cout << "\nExecution stopped by user" << std::endl;
    exit(signum);
}

bool run_test_case(const std::string &executable, const std::string &input_file, const std::string &expected_output_file, const std::string &actual_output_file, int case_number) {
    if (!running) return false;

    auto start = std::chrono::high_resolution_clock::now();

    // Execute the executable and write output to the output file
    std::string command = executable + " < " + input_file + " > " + actual_output_file;
    system(command.c_str());

    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> duration = end - start;

    // Read the expected output
    std::ifstream expected_file(expected_output_file);
    std::string expected_output((std::istreambuf_iterator<char>(expected_file)), std::istreambuf_iterator<char>());
    expected_file.close();

    // Read the actual output
    std::ifstream actual_file(actual_output_file);
    std::string actual_output((std::istreambuf_iterator<char>(actual_file)), std::istreambuf_iterator<char>());
    actual_file.close();

    if (actual_output == expected_output) {
        std::cout << "Case #" << case_number << ": ACCEPT [Time: " << duration.count() << "s]" << std::endl;
        return true;
    } else {
        std::cout << "Case #" << case_number << ": WRONG ANSWER [Time: " << duration.count() << "s]" << std::endl;
        std::cout << "Expected Output:\n" << expected_output << std::endl;
        std::cout << "Your Output:\n" << actual_output << std::endl;
        return false;
    }
}

void run_all_tests(const std::string &executable) {
    int test_case_index = 0;

    while (running) {
        std::string input_file = "in" + std::to_string(test_case_index);
        std::string expected_output_file = "ans" + std::to_string(test_case_index);
        std::string actual_output_file = "output" + std::to_string(test_case_index);

        std::ifstream input(input_file);
        std::ifstream expected(expected_output_file);

        if (!input.good() || !expected.good()) {
            break;
        }

        if (!run_test_case(executable, input_file, expected_output_file, actual_output_file, test_case_index)) {
            break;
        }

        test_case_index++;
    }
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " <executable>" << std::endl;
        return 1;
    }

    std::string executable = argv[1];

    // Register signal handler
    signal(SIGINT, signalHandler);

    run_all_tests(executable);

    return 0;
}
