#define _CRT_SECURE_NO_WARNINGS
using namespace std;

#if __cplusplus >= 201703L
#include <filesystem>
#endif

#include "CompilationSupervisor.h"    
#include "RunSupervisor.h"    
#include "Global.h"
#include <signal.h>
#ifndef _WIN32
#include <unistd.h>
#else

#endif

//https://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D0%B3%D0%BD%D0%B0%D0%BB_(Unix)
void hdl(int sig)
{
   String file_name  = "GOT_SIGNAL_AT_"+ String(Utils::getAbsoluteTime());
   FILE * res = fopen(file_name.getCharArray(),"w");
   fprintf(res, "%d\n", sig);
   fclose(res);
}
void set_handlers() {
#ifndef _WIN32
	struct sigaction act;
	memset(&act, 0, sizeof(act));
	act.sa_handler = hdl;
	sigset_t   set;
	sigemptyset(&set);
	//---
	sigaddset(&set, SIGABRT);
	sigaddset(&set, SIGALRM);
	sigaddset(&set, SIGBUS);
	sigaddset(&set, SIGVTALRM);
    sigaddset(&set, SIGFPE);
    sigaddset(&set, SIGHUP);
    sigaddset(&set, SIGILL);
	sigaddset(&set, SIGINT);
    sigaddset(&set, SIGPIPE);
    sigaddset(&set, SIGQUIT);
    sigaddset(&set, SIGSEGV);
	sigaddset(&set, SIGTERM);
	sigaddset(&set, SIGTSTP);
	sigaddset(&set, SIGTTIN);
	sigaddset(&set, SIGTTOU);
	sigaddset(&set, SIGUSR1);
	sigaddset(&set, SIGUSR2);
    sigaddset(&set, SIGPOLL);
    sigaddset(&set, SIGPROF);
	sigaddset(&set, SIGSYS);
	sigaddset(&set, SIGTRAP);
	//sigaddset(&set, SIGURG);
	//sigaddset(&set, SIGCHLD);
	//sigaddset(&set, SIGCONT);
	sigaddset(&set, SIGVTALRM);
	sigaddset(&set, SIGXCPU);
	sigaddset(&set, SIGXFSZ);
	//---
	act.sa_mask = set;
	//---
	sigaction(SIGABRT, &act, 0);
	sigaction(SIGALRM, &act, 0);
	sigaction(SIGBUS, &act, 0);
	sigaction(SIGVTALRM, &act, 0);
	sigaction(SIGFPE, &act, 0);
	sigaction(SIGHUP, &act, 0);
	sigaction(SIGILL, &act, 0);
	sigaction(SIGINT, &act, 0);
	sigaction(SIGPIPE, &act, 0);
	sigaction(SIGQUIT, &act, 0);
	sigaction(SIGSEGV, &act, 0);
	sigaction(SIGTERM, &act, 0);
	sigaction(SIGTSTP, &act, 0);
	sigaction(SIGTTIN, &act, 0);
	sigaction(SIGTTOU, &act, 0);
	sigaction(SIGUSR1, &act, 0);
	sigaction(SIGUSR2, &act, 0);
	sigaction(SIGPOLL, &act, 0);
	sigaction(SIGPROF, &act, 0);
	sigaction(SIGSYS, &act, 0);
	sigaction(SIGTRAP, &act, 0);
	sigaction(SIGVTALRM, &act, 0);
	sigaction(SIGXCPU, &act, 0);
	sigaction(SIGXFSZ, &act, 0);
#endif
}

void getEnv_(String& res, const char * name_in){
    char * value_ = getenv(name_in);
    if (value_ != NULL){
         res = String(value_);
         value_ = NULL;
    }
}

int main(int argc, char ** argv)      
{
    //+
    set_handlers();
    //-
	userWorkspace = String(argv[1]);   
	packageWorkspace = String(argv[2]);   
	maxKernels = atoi(argv[3]);   
	dvm_drv = String(argv[4]); 
	//--   
	freeKernels = maxKernels;
	busyKernels= 0;	   
	//--
	getEnv_(PATH,"PATH");
	getEnv_(LD_LIBRARY_PATH,"LD_LIBRARY_PATH");
    //--
    ("PATH="+PATH).println();
    ("LD_LIBRARY_PATH="+LD_LIBRARY_PATH).println();
    //--
    packageId = Utils::getFileName(packageWorkspace);
#if __cplusplus >= 201703L
	std::filesystem::current_path(packageWorkspace.getCharArray());
#else
	chdir(packageWorkspace.getCharArray());
#endif
	userWorkspace.println();
	packageWorkspace.println();
	printf("%d\n", maxKernels);

#ifndef _WIN32	
	int pid = getpid();
#else
	int pid = _getpid();
#endif

	printf("PID=%d\n", pid);
	File pidFile("PID", String(pid)+"\n");
	pidFile.Close();
	//---
	File startFile("STARTED", "+");
    startFile.Close();
    //---
	printf(">>>>\n");
	CompilationSupervisor * compilationSupervisor = new CompilationSupervisor();
	compilationSupervisor->DoWithSchedule(maxKernels);
	RunSupervisor * runSupervisor = new RunSupervisor(compilationSupervisor);
	runSupervisor->DoWithSchedule(maxKernels);  
	return 0;      
}      
