//============================================================================
// Name        : cluto_parser.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <string>
#include <sstream>
#include <iterator>
#include <vector>
#include <map>
#include <fstream>
#include <algorithm>
using namespace std;

#include <matrices/io/SuperMatrixWriter.h>
#include <matrices/io/SuperMatrixReader.h>
#include <matrices/utils.h>

typedef std::map<std::string, size_t> TokenFreq;
typedef std::map<std::string, TokenFreq> Data;


void split(
	std::string pText,
	std::vector<std::string>& pResult,
	const char pDelim = ' ')
{
	std::stringstream ss(pText);
	std::string item;
	while(std::getline(ss, item, pDelim)){
		pResult.push_back(item);
	}
}


void dumpData(Data const& pData){
	for(Data::const_iterator i=pData.begin(); i!=pData.end(); ++i){
		std::cout << i->first << "=[";
		for(TokenFreq::const_iterator t=i->second.begin(); t!=i->second.end(); ++t){
			std::cout << t->first << ":" << t->second << ", ";
		}
		std::cout << "];" << std::endl;
	}
}


void parseFiles(
	std::vector<std::string> const& pFiles,
	Data& pData)
{
	for(size_t i=0; i<pFiles.size(); ++i){
		std::fstream dataFile(pFiles[i].c_str(), std::ios_base::in);
		std::fstream rowsFile((pFiles[i] + ".rlabel").c_str(), std::ios_base::in);

		std::string rowLine, dataLine;
		while(std::getline(rowsFile, rowLine)){
			std::getline(dataFile, dataLine);

			std::vector<std::string> tokens;
			split(dataLine, tokens);

			rowLine.erase(--rowLine.end());
			for(size_t t=0; t<tokens.size(); ++t)
				++pData[rowLine][tokens[t]];
		}

		rowsFile.close();
		dataFile.close();
	}
}


void start(std::vector<std::string> const& pFiles){
	Data pData;
	parseFiles(pFiles, pData);

	std::cout << "files parsed" << std::endl;

	std::map<std::string, size_t> uniqueCols;
	{
		for(Data::iterator i=pData.begin(); i!=pData.end(); ++i)
			for(TokenFreq::iterator t=i->second.begin(); t!=i->second.end(); ++t)
				if(uniqueCols.find(t->first) == uniqueCols.end())
					uniqueCols.insert(std::pair<std::string, size_t>(t->first, uniqueCols.size()));
	}

	size_t rows = pData.size();
	size_t cols = uniqueCols.size();

	Matrices::FeatureVectorPtr colsFeatures(new Matrices::FeatureVector(cols));
	{
		for(std::map<std::string, size_t>::iterator i=uniqueCols.begin(); i!=uniqueCols.end(); ++i)
			(*colsFeatures)[i->second].SetLabel(i->first);
	}

	std::cout << "building" << std::endl;

	Matrices::CRSMatrixPtr crs(new Matrices::CRSMatrix("crs", rows, cols));
	Matrices::FeatureVectorPtr rowsFeatures(new Matrices::FeatureVector(rows));
	{
		size_t rf=0;
		for(Data::iterator i=pData.begin(); i!=pData.end(); ++i){
			(*rowsFeatures)[rf].SetLabel(i->first);
			for(TokenFreq::iterator t=i->second.begin(); t!=i->second.end(); ++t){
				size_t fidx = uniqueCols[t->first];
				crs->SetCell(t->second, rf, fidx);
			}
			++rf;
		}
	}

	std::cout << "creating" << std::endl;

	Matrices::SuperMatrixPtr mtx(new Matrices::SuperMatrix(
		"clutodocs", Matrices::CCSMatrixPtr(), crs, rowsFeatures, colsFeatures, 0, "no desc"));
	mtx->SyncCRSToCCS();

	std::cout << "updating features" << std::endl;

	Matrices::update_features(mtx, true);

	std::cout << "writing" << std::endl;

	Matrices::IO::WriteSuperMatrix(mtx, "/home/michalw/Dokumenty/macierze/");

	std::cout << "done" << std::endl;
}



int main() {
	std::vector<std::string> files;
	files.push_back("/home/michalw/Dokumenty/socjo/cluto-base");
	files.push_back("/home/michalw/Dokumenty/socjo/cluto-pairs");
	files.push_back("/home/michalw/Dokumenty/socjo/cluto-triples");

	start(files);

	return 0;
}
