/*
    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.
*/

#include "GensimMatrixWriter.h"
#include "../matrices_headers.h"
#include "CCSMatrixWriter.h"

#include "filesystem_error.h"

#include "defines.h"

static log4cxx::LoggerPtr logger(log4cxx::Logger::getLogger("SuperMatrix.matrices.io.GensimMatrixWriter"));

namespace Matrices
{
	namespace IO
	{

		void GensimMatrixWriter::Write(Matrices::SuperMatrixPtr m_pMatrix, std::string &path) throw(filesystem_error)
		{
			LOG4CXX_INFO(logger, "Writing gensim matrix " << m_pMatrix->GetName() << "...");

			PrepareDir(m_pMatrix, path);

			namespace fs = boost::filesystem;
			fs::path base(path);
			base /= m_pMatrix->GetName();
			fs::path rowlabels = base.string()+"/"+GENSIM_DICTIONARY_NAME;
			std::string base_str = base.string()+"/"+GENSIM_MATRIX_NAME;
			WriteMatrixMarket(m_pMatrix, base_str);
			WriteId2Word(m_pMatrix->GetRowFeatures(), rowlabels.string());
			LOG4CXX_INFO(logger, "Writing gensim matrix " << m_pMatrix->GetName() << "... done");
		}

		void GensimMatrixWriter::PrepareDir(SuperMatrixPtr pMatrix, std::string &path)
		{
			namespace fs = boost::filesystem ;

			fs::path dir(path);
			dir.normalize();
			if( ! fs::exists(dir) )
			{
				fs::create_directory(dir);
				if( ! fs::exists(dir) )
					throw IO::filesystem_error( std::string("Cannot create directory: ") + dir.string() );
			}
			if( ! fs::is_directory(dir) )
				throw IO::filesystem_error( std::string("Given path is not a directory: ") + dir.string() );
			fs::path store_dir = dir / pMatrix->GetName();
			if( ! fs::exists(store_dir) )
			{
				fs::create_directory(store_dir);
				if( ! fs::exists(store_dir) )
					throw IO::filesystem_error( std::string("Cannot create directory: ") + store_dir.string() );
			}
		}



		void GensimMatrixWriter::WriteId2Word(FeatureVectorPtr v, const std::string &filename)
		{
			std::ofstream file( filename.c_str() );
			if(!file)
				throw filesystem_error( "Cannot open file for writing: " + filename );

			for(size_t i = 0; i < v->size(); i++)
			{
				Feature & f = (*v)[i];
				file << i << "\t" << f.GetLabel() << "\t" << f.GetTermFrequency() << std::endl;
			}
			file.close();

		}

		void GensimMatrixWriter::WriteMatrixMarket(SuperMatrixPtr pMatrix, std::string &path)
		{
			Matrices::CRSMatrixPtr crs=pMatrix->GetCRS();
			Matrices::CCSMatrixPtr ccs=pMatrix->GetCCS();

			size_t nz = 0;
			for(size_t row_no = 0; row_no < crs->NumberOfRows(); row_no++)
				nz += crs->GetCompressedRow(row_no)->GetValues()->size();

			std::ofstream file(path.c_str());
			if(!file)
				throw filesystem_error( "Cannot open file for writing: " + path);
			file << "%%MatrixMarket matrix coordinate real general" <<std::endl;
			file << crs->NumberOfRows()<< " "  << crs->NumberOfColumns() << " " << nz << std::endl;

			for(size_t column_no = 0; column_no < crs->NumberOfRows(); column_no++)
			{
				std::map<size_t, double>* vals = crs->GetCompressedRow(column_no)->GetValues();
				for(std::map<size_t, double>::iterator iter = vals->begin(); iter != vals->end(); iter++)
				{

					file << column_no+1 << " " << iter->first+1 << " " << iter->second << " ";
					if(iter->second==0)
					LOG4CXX_WARN(logger,"Warning: inserted value 0 into output file!");
					file << std::endl;
				}


			}

			file.close();
		}

		void WriteGensimMatrix(SuperMatrixPtr m, const std::string &dir)
		{
			GensimMatrixWriter writer;
			    std::string p = dir;
			    writer.Write(m, p);
		}
	}
}
