// IO.cpp

#include "IO.h"
#include "GrayCode.h"

IO::IO(){}
IO::~IO(){}

uint IO::GetEntry(string s, uint n)
{
	cout << s << n << "\n" << "Enter x to accept default, else New Entry = ";

	uint nIn = 0;
	cin >> nIn;

	if (cin.fail())
	{
		return n;
	}
	return nIn;
}

bool IO::FindInVector(uint a, vector<uint> v)
{
	for (uint n = 0; n < v.size(); n++)
	{
		if (a == v[n]) return true;
	}
	return  false;
}

uint IO::FindInVectorCount(uint a, vector<uint> v)
{
	uint nCount = 0;
	for (uint n = 0; n < v.size(); n++)
	{
		if (a == v[n])
			nCount++;
	}
	return  nCount;
}

void IO::UpDateCorrectTieErrorTotal(vector<uint>& vCorrectTieErrorTotal, uint nCorrectClass, vector<uint> vTestClasses)
{
	if (vCorrectTieErrorTotal.size() == 4 && vTestClasses.size() > 0)
	{
		if (vTestClasses.size() == 1 && nCorrectClass == vTestClasses[0])
		{
			vCorrectTieErrorTotal[0]++;						// correct
		}
		else if (FindInVector(nCorrectClass, vTestClasses))
		{
			vCorrectTieErrorTotal[1]++;						// tie
		}
		else
		{
			vCorrectTieErrorTotal[2]++;						// error
		}
		vCorrectTieErrorTotal[3]++;
	}
	else
	{
		cout << "\n*** Error: MeasureOfSimilarity::UpDateCorrectTieErrorTotal ***\n";
	}
}

string IO::DumpVector(uint nSpaceType, vector<bool> v)
{
	ostringstream ss;
	for (uint n = 0; n < v.size(); n++)
	{
		ss << v[n];

		if (n < v.size() - 1)
		{
			if (nSpaceType == 1)
				ss << " ";
			else if (nSpaceType == 2)
				ss << "\t";
		}
	}
	return ss.str();
}

string IO::DumpVector(uint nSpaceType, vector<uint> v)
{
	ostringstream ss;
	for (uint n = 0; n < v.size(); n++)
	{
		ss << v[n];

		if (n < v.size() - 1)
		{
			if (nSpaceType == 1)	// nSpaceType == 0 means no space
				ss << " ";
			else if (nSpaceType == 2)
				ss << "\t";
		}
	}
	return ss.str();
}

string IO::DumpVector(uint nDefault, uint nSpaceType, vector<uint> v)
{
	ostringstream ss;
	for (uint n = 0; n < v.size(); n++)
	{
		if (v[n] == nDefault)
			ss << "\t\t";
		else
			ss << v[n];

		if (n < v.size() - 1)
		{
			if (nSpaceType == 1)	// nSpaceType == 0 means no space
				ss << " ";
			else if (nSpaceType == 2)
				ss << "\t";
		}
	}
	return ss.str();
}

string IO::DumpMapWithDefaultSpacing(uint nDefault, uint nSpaceType, map<vector<bool>, vector<uint>> m)
{
	GrayCode cGC = GrayCode();

	ostringstream ss;
	map<vector<bool>, vector<uint>>::iterator i;

	cout << "\nSFC Size = " << m.size() << "\n";
	ss << "\nSize = " << m.size() << "\n";

	for (i = m.begin(); i != m.end(); i++)
	{
		ss << DumpVector(nDefault, nSpaceType, i->second);
		ss << "\n";
	}
	return ss.str();
}

string IO::DumpMapWithDefaultSpacing(bool bClassCount, uint nDefault, uint nSpaceType, map<vector<bool>, vector<uint>> m)
{
	GrayCode cGC = GrayCode();

	ostringstream ss;
	map<vector<bool>, vector<uint>>::iterator i;

	cout << "\nSFC Size = " << m.size() << "\n";
	ss << "\nSize = " << m.size() << "\n";

	uint nCount = 0;
	for (i = m.begin(); i != m.end(); i++)
	{
		ss << nCount << "\t\t";
		ss << DumpVector(nDefault, nSpaceType, i->second);

		if (bClassCount)
		{
			uint nClassCount = 0;
			uint nClassDefault = 10;
			uint nDefaultCount = 0;
			vector<uint> vSumsIndexesClasses = i->second;
			for (uint n = 0; n < vSumsIndexesClasses.size(); n++)
			{
				if (nDefaultCount == 2 && vSumsIndexesClasses[n] != nClassDefault)
				{
					nClassCount++;
				}
				if (vSumsIndexesClasses[n] == nDefault)
				{
					nDefaultCount++;
				}
			}
			ss << "\t\t";
			ss << nClassCount;
		}
		nCount++;
		ss << "\n";
	}
	return ss.str();
}

string IO::DumpMapWithDefaultSpacing(bool bGraySums, vector<uint> vGrayStart, vector<uint> vGraySize, bool bClassCount, uint nDefault, uint nSpaceType, map<vector<bool>, vector<uint>> m)
{
	GrayCode cGC = GrayCode();

	ostringstream ss;
	map<vector<bool>, vector<uint>>::iterator i;

	cout << "\nSFC Size = " << m.size() << "\n";
	ss << "\nSize = " << m.size() << "\n";

	for (i = m.begin(); i != m.end(); i++)
	{
		if (bGraySums)
		{
			vector<uint> vGraySums = cGC.GraySums(vGrayStart, vGraySize, cGC.Base2ToGray(i->first));
			ss << DumpVector(nSpaceType, vGraySums) << "\t\t";
		}

		ss << DumpVector(nDefault, nSpaceType, i->second);

		if (bClassCount)
		{
			uint nClassCount = 0;
			uint nClassDefault = 10;
			uint nDefaultCount = 0;
			vector<uint> vSumsIndexesClasses = i->second;
			for (uint n = 0; n < vSumsIndexesClasses.size(); n++)
			{
				if (nDefaultCount == 2 && vSumsIndexesClasses[n] != nClassDefault)
				{
					nClassCount++;
				}
				if (vSumsIndexesClasses[n] == nDefault)
				{
					nDefaultCount++;
				}
			}
			ss << "\t\t";
			ss << nClassCount;
		}
		ss << "\n";
	}
	return ss.str();
}

string IO::DumpMap(uint nSpaceType, map<uint, vector<uint>> m)
{
	ostringstream ss;
	map<uint, vector<uint>>::iterator i;

	cout << "SFC Size = " << m.size() << "\n";
	ss << "Size = " << m.size() << "\n";

	for (i = m.begin(); i != m.end(); i++)
	{
		ss << i->first;
		ss << "\t\t";
		ss << DumpVector(nSpaceType, i->second);
		ss << "\n";
	}
	return ss.str();
}

string IO::DumpMap(uint nSpaceType, map<vector<uint>, uint > m)
{
	ostringstream ss;
	map<vector<uint>, uint >::iterator i;

	cout << "SFC Size = " << m.size() << "\n";
	ss << "Size = " << m.size() << "\n";

	for (i = m.begin(); i != m.end(); i++)
	{
		ss << DumpVector(nSpaceType, i->first);
		ss << "\t\t";
		ss << i->second;
		ss << "\n";
	}
	return ss.str();
}

string IO::DumpMap(uint nSpaceType, map<vector<bool>, vector<uint>> m)
{
	GrayCode cGC = GrayCode();

	ostringstream ss;
	map<vector<bool>, vector<uint>>::iterator i;

	cout << "\nSFC Size = " << m.size() << "\n";
	ss << "\nSize = " << m.size() << "\n";

	for (i = m.begin(); i != m.end(); i++)
	{
		ss << DumpVector(nSpaceType, i->second);
		ss << "\n";
	}
	return ss.str();
}

string IO::DumpMap(uint nSpaceType, map<vector<uint>, vector<uint>> m)
{
	GrayCode cGC = GrayCode();

	ostringstream ss;
	map<vector<uint>, vector<uint>>::iterator i;

	cout << "SFC Size = " << m.size() << "\n";
	ss << "Size = " << m.size() << "\n";

	for (i = m.begin(); i != m.end(); i++)
	{
		ss << DumpVector(nSpaceType, i->second);
		ss << "\n";
	}
	return ss.str();
}

string IO::DumpMap(bool bGray, uint nSpaceType0, uint nSpaceType1, map<vector<bool>, vector<uint>> m)
{
	GrayCode cGC = GrayCode();

	ostringstream ss;
	map<vector<bool>, vector<uint>>::iterator i;

	cout << "SFC Size = " << m.size() << "\n";
	ss << "Size = " << m.size() << "\n";

	for (i = m.begin(); i != m.end(); i++)
	{
		ss << DumpVector(nSpaceType0, i->first);
		ss << "\t\t";

		if (bGray)
		{
			ss << DumpVector(nSpaceType0, cGC.Base2ToGray(i->first));
			ss << "\t\t";
		}
		ss << DumpVector(nSpaceType1, i->second);
		ss << "\n";
	}
	return ss.str();
}

string IO::DumpMap(bool bGray, uint nDefault, uint nSpaceType0, uint nSpaceType1, map<vector<bool>, vector<uint>> m)
{
	GrayCode cGC = GrayCode();

	ostringstream ss;
	map<vector<bool>, vector<uint>>::iterator i;

	cout << "SFC Size = " << m.size() << "\n";
	ss << "Size = " << m.size() << "\n";

	for (i = m.begin(); i != m.end(); i++)
	{
		ss << DumpVector(nSpaceType0, i->first);
		ss << "\t\t";

		if (bGray)
		{
			ss << DumpVector(nSpaceType0, cGC.Base2ToGray(i->first));
			ss << "\t\t";
		}
		ss << DumpVector(nDefault, nSpaceType1, i->second);
		ss << "\n";
	}
	return ss.str();
}

string IO::DumpMap(uint nSpaceType0, uint nSpaceType1, map<vector<uint>, vector<uint>> m)
{
	GrayCode cGC = GrayCode();

	ostringstream ss;
	map<vector<uint>, vector<uint>>::iterator i;

	cout << "SFC Size = " << m.size() << "\n";
	ss << "Size = " << m.size() << "\n";

	for (i = m.begin(); i != m.end(); i++)
	{
		ss << DumpVector(nSpaceType0, i->first);
		ss << "\t\t";

		ss << DumpVector(nSpaceType1, i->second);
		ss << "\n";
	}
	return ss.str();
}

bool IO::WriteFile(string sFile, string s)
{
	ofstream f(sFile.c_str());
	if (!f)
	{
		s += "\n";
		s += "error: unable to open ";
		s += sFile;
		s += "\n";

		cout << "\nerror: unable to open " << sFile.c_str() << "\n";
		return false;
	}
	f << s;
	f.close();
	return true;
}

string IO::DumpVectorMatrix(vector<bool> v)
{
	ostringstream ss;
	uint nSize = (uint)v.size();
	uint nSide = (uint)sqrt((double)nSize);

	for (uint n = 0; n < v.size(); n++)
	{
		if (v[n])
			ss << "1";
		else
			ss << "0";

		if ((n + 1) % nSide == 0)
			ss << "\n";
	}
	ss << "\n";
	return ss.str();
}

