/*
    Copyright (C) 2012 Bartosz Broda, Jacek Bochenek, Łukasz Biłeńkij, 
    Damian Jaworski, Wojciech Mazur, Dominik Piasecki, Maciej Piasecki, 
    Radosław Ramocki
    
    This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option)
any later version.

    This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. 

    See the LICENSE and COPYING files for more details.
*/

#ifndef PARALLELHAL_H
#define PARALLELHAL_H
#include "Architect.h"
#include "Config.h"
#include "../mpi_handler/mpi_handler.h"
#include "UnigramDictionary.h"
#include "MatrixSaver.h"


#define GIVE_JOB -150000
#define EXIT_CODE -150001
#define SENDING_RESULTS -150002
#define SENDING_CORPUS_SIZE -150003
#define SENDING_DICT -150004
#define NOT_YET -150005
#define ALL_OK -150006


namespace parallel
{
	namespace hal_architect
	{
		class ParallelHalMaster
		{
		public:
			/**
			  * Constructor
			  */
			ParallelHalMaster();
			/**
			  * Initializes architect, sets variables
			  */
			void Init();
			/**
			  * Starts job of parallel master. Divides work to nodes, collects results
			  */
			void Start();
			/**
			  * Finalizes job, saves matrix and dictionary to files
			  */
			void Finalize();
		private:
			/**
			  * Saves dictionary to file
			  */
			void saveDict();
			/**
			  * Sends task (corpus) to node with given number
			  */
			void sendJob(int nodeNum);
			/**
			  * Receives results from specified node
			  */
			void receiveResults(int nodeNum);
			/**
			  * Receives dictionary from specified node
			  */
			void receiveDict(int nodeNum);
			int numOfNodes;
			int tasksGiven;
			int totalTasks;
			MPI_Handler mpiHandler;
			int resultsReceived;
			int corpusSize;
			::hal_architect::Architect arch;
			std::map<std::string, int> wordTF;



		};

		class ParallelHalSlave
		{
		public:
			/**
			  * Empty constructor
			  */
			ParallelHalSlave();
			/**
			  * Function initializing variables
			  */
			void Init(int myRank);
			/**
			  * Function starting slave job. Gets task, computes, sends results
			  */
			void Start();
		private:
			/**
			  * Sends dictionary to master
			  */
			void sendDict();
			/**
			  * Sends result part of matrix to master
			  */
			void sendResults(::hal_architect::Architect arch);
			int myRank;
			int corpusesProcessed;
			MPI_Handler mpiHandler;
		};
	}
}
#endif // PARALLELHAL_H
