#include "File.h"  
#include "Utils.h"  
#include "Global.h" 
 
#pragma once    
enum TaskState {   
	Inactive, //0 
	Waiting,  //1 
	WorkspaceCreated, //2 
	WorkspaceReady, //3 
	Running,  //4 
	Canceled,  //5 
	Finished,  //6 
	FinishedAbortedByTimeout, //7  
	FinishedAbortedByUser,  //8 
	Done, //9 
	DoneWithErrors, //10 
	AbortedByTimeout, //11 
	AbortedByUser,  //12 
	Crushed,  //13 
	WrongTestFormat, //14    
	InternalError,  //15 
	Queued, //16 
	NoSuchTask, //17  
	FailedToQueue,  //18 
	AbortingByUser  //19 
};   
#pragma once
enum TestType{
	Default, //0
	Correctness, //1
	Performance, //2
};

#pragma once    
class Task {   
protected:	   
	long id;   
	int maxtime;  
	int kernels; //получение зависит от типа задачи.
	String workspace;	  
	TaskState state;   
public:   
	String printState(){ 
		switch(state){ 
			case Inactive: 
				return String("Inactive"); 
			case Waiting: 
				return String("Waiting"); 
			case WorkspaceCreated: 
				return String("WorkspaceCreated"); 
			case WorkspaceReady: 
				return String("WorkspaceReady"); 
			case Running: 
				return String("Running"); 
			case Canceled: 
				return String("Canceled"); 
			case Finished: 
				return String("Finished"); 
			case FinishedAbortedByTimeout: 
				return String("FinishedAbortedByTimeout"); 
			case FinishedAbortedByUser: 
				return String("FinishedAbortedByUser"); 
			case Done: 
				return String("Done"); 
			case DoneWithErrors: 
				return String("DoneWithErrors"); 
			case AbortedByTimeout: 
				return String("AbortedByTimeout"); 
			case AbortedByUser: 
				return String("AbortedByUser"); 
			case Crushed: 
				return String("Crushed"); 
			case WrongTestFormat: 
				return String("WrongTestFormat"); 
			case InternalError: 
				return String("InternalError"); 
			case Queued: 
				return String("Queued"); 
			case NoSuchTask: 
				return String("NoSuchTask"); 
			case FailedToQueue: 
				return String("FailedToQueue"); 
			case AbortingByUser: 
				return String("AbortingByUser");	 
			default: 
				return "?";			 
		} 
	} 
	//-------------->> 
	long getId(){return id;}   
	long setId(String * id_s){   
		return id=strtol(id_s->getCharArray(), NULL, 10);   
	}   
	int getMaxtime(){return maxtime;}   
	int setMaxtime(String * maxtime_s){   
		return maxtime=atoi(maxtime_s->getCharArray());   
	}   
	const String& getWorkspace(){return workspace;}
	TaskState getState(){return state;}   
	TaskState setState(TaskState state_in){return state=state_in;}  
	Task(Text * lines, int offset){ 	 
		setId(lines->get(offset));		     
		setMaxtime(lines->get(offset+1)); 
		workspace = packageWorkspace+"/"+String(id); 
	}  
	virtual void print()=0;   
	//- 	 
	virtual void prepareWorkspace(){} 	 
	virtual String getLaunchScriptText()=0; 
	virtual String getStartCommand(){ 
		return workspace+"/run"; 
	}	 
 
	void createWorkspace(){ 
		Utils::Mkdir(workspace); 
	}  
	void createLaunchScript(){ 
		String launchScriptPath = workspace+"/run";  
		String launchScriptText =  
			String("cd ")+String::DQuotes(workspace)+"\n"+			 
			getLaunchScriptText();		 
		File launchScriptFile = File(launchScriptPath, launchScriptText); 
		Utils::Chmod(launchScriptPath); 
	} 
	virtual void Start(){		 
		 
		if (kernels<=freeKernels){		 
			system(getStartCommand().getCharArray()); 
			state=Running; 
			//- 
			busyKernels= Utils::min(busyKernels+kernels, maxKernels); 
			freeKernels= Utils::max(0, maxKernels-busyKernels);			 
			//- 
		} 
	} 
	virtual void analyseResults(){
		state=Finished;
	}
	virtual void Check(){ 
		if (Utils::Exists(workspace+"/DONE")){ 
			analyseResults();
		}else { 
			if (Utils::Exists(workspace+"/TIMEOUT")){ 
				state=AbortedByTimeout; 
				//todo определить по интервалу времени на всякий случай.
			}else if (Utils::Exists(workspace+"/INTERRUPT")){ 
				state=AbortedByUser;	 
			} 
		} 
		if (state!=Running){ 
			//- 
			busyKernels= Utils::min(busyKernels-kernels, maxKernels); 
			freeKernels= Utils::max(0, maxKernels-busyKernels); 
			//- 
			saveState(); //не нужно. только для отладки. анализ будет делаться архивом.
		}		 
	} 
	virtual void saveState(){ 
		String stateFile = workspace+"/TaskState"; 
		File(stateFile, printState()); 
	} 
};   
