#include "File.h"   
#include "Task.h"   
#include <unistd.h>  

#pragma once     
enum SupervisorState {   
    WorkspacesCreation, //0   
    Preparation,		//1   
    Execution,		//2   
    Archivation,        //3
    End			//4   
};    
#pragma once     
template <class T>     
class Supervisor : public Array <T> {   
protected:
	SupervisorState state;   
public:    
	virtual String getStatePrefix(){
		return String("");
	}
	String printState(){
		switch(state){
			case WorkspacesCreation:
				return String("WorkspacesCreation");
			case Preparation:
				return String("Preparation");
			case Execution:
				return String("Execution");
			case Archivation:
				return String("Archivation");
			case End:
				return String("End");			 
			default: 
				return "?";			 
		} 
	}
	//-
	void print(){     
		for (long i=0; i< this->length; ++i)     
			this->elements[i]->print();      
	}		  
	void init(const char * fileName, int recordSize){    
		state = WorkspacesCreation;   
		File * packedTasks = new File(fileName);      
		Text * lines = packedTasks->readLines();	      
		this->length = lines->getLength()/recordSize;    
		this->elements = new T* [this->length];       
		int offset=0;      
		for (int i=0; i< this->length; ++i){   
			this->elements[i]= new T(lines, offset);  
			offset+=recordSize;      
		}      
		delete packedTasks;      
		delete lines;	     
	}    
	void Do(){   
		saveState();
		long activeCount=0;	   
		//todo обязательно убрать отладочную печать.  
		printf("tasks count = %ld\n", this->length);	   
		while (this->state!= End){   
//			printf("state=%d\n", this->state);  
//			printf("max=%d; busy=%d; free=%d\n", maxKernels, busyKernels, freeKernels);			   
			activeCount=0;   
			for (long i=0; i<this->length; ++i){   
				T * task = this->elements[i]; 				  
				switch (this->state){   
					case WorkspacesCreation:   
						if (task->getState()==Waiting){   
							activeCount++;   
							task->createWorkspace(); 		
							task->setState(WorkspaceCreated);					  
						}   
						break; 						  
					case Preparation:   
						if (task->getState()==WorkspaceCreated){   
							activeCount++;   
							task->prepareWorkspace();   
							task->createLaunchScript();
							task->setState(WorkspaceReady);							  
						}   
						break;						  
					case Execution:  
						if (task->getState()==WorkspaceReady){  
							activeCount++;  
							task->Start();							  
						}else if (task->getState()==Running){  
							activeCount++;  
							task->Check();  
						}														  
						break;  
					default:   
//						printf("id = %ld; state = %d\n", task->getId(), task->getState());   
						break;   
				}   
			}   
//			printf("active count = %d\n", activeCount);   
			if (activeCount==0){				   
				switch (this->state){   
					case WorkspacesCreation:   
						this->state = Preparation;  
						saveState(); 
						break;   
					case Preparation:   
						this->state = Execution;
						saveState();    
						break;						  
					case Execution:  
						Finalize();
						this->state = End; 
						saveState();						
						break;  				   
					default:   
						this->state = End;
						break;   
				}   
			}  
			Utils::Sleep(2); 
		}   
	}   
	virtual void Finalize(){}
	void saveState(){
		Utils::Sleep(1); //чтобы не было одинаковых по дате файлов.
		String stateFile = packageWorkspace+"/state/"+getStatePrefix()+printState();
		//printf("stateFile=<%s>\n", stateFile.getCharArray()); 
		File(stateFile, Utils::getDate()); 
	}
};