/**
 * experimentQueueMain.cpp
 *      - compiles to bin/queue
 *      - runs through a set of controls to run the orchestrator with multiple settings over time
 *
 * Stan Gurtler
 */

#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <csignal>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

const char *ORCHESTRATOR = "bin/orchestrator";
const char *SHUT_DOWN = "scripts/bringDownTestServers.sh";
const int INPUT_BUFFER_LEN = 133;
char whichTest[INPUT_BUFFER_LEN+2];
int currPid = 0;
bool stopSignaled = false;

void exitInterruptHandler(int signum)
{
    std::cout << "Interrupt signal received, quitting." << std::endl;

    kill(-currPid, SIGINT);

    char *argv[3];
    char shutdownBuffer[INPUT_BUFFER_LEN+2];
    strncpy(shutdownBuffer, SHUT_DOWN, INPUT_BUFFER_LEN+1);

    argv[0] = shutdownBuffer;
    argv[1] = whichTest;
    argv[2] = NULL;

    int lastPid = fork();
    if (currPid < 0)
        exit(-signum);
    if (currPid == 0)
        execv(SHUT_DOWN, argv);
    else
        waitpid(lastPid, NULL, 0);

    exit(signum);
}

void gentleInterruptHandler(int signum)
{
    std::cout << "Upcoming stop signal received." << std::endl;
    std::cout << "After the current run is done, the program will quit." << std::endl;

    stopSignaled = true;
}

int main(int argc, char* argv[])
{
    signal(SIGINT, exitInterruptHandler);
    signal(SIGTSTP, gentleInterruptHandler);

    char inputBuffer[INPUT_BUFFER_LEN+2];
    std::ifstream configFile("cfg/queue.cfg");
    while (!stopSignaled && !configFile.eof())
    {
        configFile.getline(inputBuffer, INPUT_BUFFER_LEN);
        if (strlen(inputBuffer) > 0)
        {
            char *helper = strtok(inputBuffer, " ");
            char *argv[6];
            
            char orchestratorBuffer[INPUT_BUFFER_LEN+2];
            strncpy(orchestratorBuffer, ORCHESTRATOR, INPUT_BUFFER_LEN+1);
            argv[0] = orchestratorBuffer;
            argv[1] = helper;

            strncpy(whichTest, helper, INPUT_BUFFER_LEN+1);

            size_t i = 2;
            while (helper != NULL && i < 6)
            {
                helper = strtok(NULL, " ");
                argv[i] = helper;
                i++;
            }
            argv[5] = NULL;
            
            currPid = fork();
            if (currPid < 0)
            {
                std::cerr << "Problem making new exec, aborting." << std::endl;
                return 1;
            }
            else if (currPid == 0)
            {
                execv(ORCHESTRATOR, argv);
            }
            else
            {
                int status;
                waitpid(currPid, &status, 0);
                if (WIFEXITED(status))
                {
                    if (WEXITSTATUS(status) != 0)
                    {
                        std::cerr << "Something went wrong in previous run, aborting." << std::endl;
                        return 1;
                    }
                }
                else if (WIFSIGNALED(status))
                {
                    std::cerr << "Signal terminated previous run, aborting." << std::endl;
                    return 1;
                }
            }
            currPid = 0;
        }
    }

    return 0;
}