/*************************************************************************
 * This file is part of the Distributed Computation feature
 *
 * Project created in conformity with the requirements for the Degree of
 * Master of Engineering in Software Engineering, Computing and Software
 * Department, McMaster University 2012
 *
 * Author:	David Kirby
 * Supervisor: Dr. Ryan Leduc
 ************************************************************************/
#include "HostFileManager.h"

namespace DESpot
{
	string HostFileManager::hostfile = "DESpot_Hostfile";
	vector<string> HostFileManager::m_nodes = vector<string>();
	int HostFileManager::m_ctr = -1;

//_________________________________________________________________________________________________

	bool HostFileManager::hostFileExists()
	{
		struct stat buf;
		if (stat(hostfile.c_str(), &buf) != -1)
			return true;
		else
			return false;
	}

//_________________________________________________________________________________________________

	void HostFileManager::createHostFile()
	{
		if (!hostFileExists())
		{
			saveHostFile("");
		}
	}

//_________________________________________________________________________________________________

	void HostFileManager::loadHostFile()
	{
		m_nodes.clear();

		std::ifstream file(hostfile.c_str());
		if (file.is_open())
		{
			std::string line;
						
			bool first = true; // indicate whether the first line has been read yet. it should be localhost, so we will skip it if it is

			while (file.good())
			{
				std::getline(file, line);

				// trim whitespace
				std::stringstream trimmer;
				trimmer << line;
				line.clear();
				trimmer >> line;

				// filter out the first line localhost, if it exists
				if (first)
				{
					first = false;
					if (line.compare("localhost") != 0)
					{
						// only store non-empty strings
						if (!line.empty())
							m_nodes.push_back(line);
					}
				}
				else
				{
					// only store non-empty strings
					if (!line.empty())
						m_nodes.push_back(line);
				}
			}
			file.close();
			m_ctr = 0;
		}		
	}

//_________________________________________________________________________________________________

	void HostFileManager::saveHostFile(string nodes)
	{
		// write to file
		std::ofstream file(hostfile.c_str());
		if (file.is_open())
		{			
			// first write the localhost for the master
			file << "localhost\n";

			// then write the slave nodes
			file << nodes;
			file.close();
		}
		else
			throw new EX("Unable to open file for save");

		// update local list of nodes
		m_nodes.clear();
		m_ctr = -1;
		loadHostFile();
	}

//_________________________________________________________________________________________________

	void HostFileManager::first()
	{
		if (m_ctr < 0)
			loadHostFile();

		if (m_ctr < 0)
			return;

		m_ctr = 0;
	}

//_________________________________________________________________________________________________

	void HostFileManager::next()
	{
		if (m_ctr < 0)
			loadHostFile();
		
		if (m_ctr < 0)
			return;

		m_ctr++;
	}

//_________________________________________________________________________________________________

	string HostFileManager::getCurrent()
	{
		if (m_ctr < 0)
			loadHostFile();

		if (m_ctr < 0)
			return "";

		if (m_ctr >= m_nodes.size())
			throw new EX("Index out of bounds");

		return m_nodes[m_ctr];
	}

//_________________________________________________________________________________________________

	bool HostFileManager::done()
	{
		if (m_ctr < 0)
			loadHostFile();

		if (m_ctr < 0)
			return true;

		return m_ctr >= m_nodes.size();
	}

//_________________________________________________________________________________________________

	int HostFileManager::length()
	{
		if (m_ctr < 0)
			loadHostFile();

		if (m_ctr < 0)
			return -1;

		return m_nodes.size();
	}

//_________________________________________________________________________________________________

	string HostFileManager::getHostFileName()
	{
		return hostfile;
	}
}
