/*
    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 "../matrices_headers.h"
#include "CCSMatrixWriter.h"

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

namespace Matrices
{
	namespace IO
	{
		CCSMatrixWriter::CCSMatrixWriter(const std::string &dir, const std::string &s)
			: CCSMultiFileWriter(dir, s)
		{
		}

		void CCSMatrixWriter::WriteMatrix(CCSMatrix &matrix)
		{
			boost::filesystem::path dir = boost::filesystem::path(dirpath);
			dir.normalize();


			name = matrix.GetName();

			// if not exists -> create
			if( !boost::filesystem::exists(dir) )
			{
				boost::filesystem::create_directory(dir);
			}

			// if is file -> throw
			if( !boost::filesystem::is_directory(dir) )
				throw filesystem_error("CCSMatrixWriter::Write", dir.string() + " is not a direcotry!");

			dir /= name;
			boost::filesystem::create_directory(dir);


			// konwersja macierz -> listy
			ConvertToLists(matrix);

			rows = matrix.NumberOfRows();
			cols = matrix.NumberOfColumns();
			nonzeros = vals->size();
			SaveToFile(dir.string());

			this->rowind->clear();
			this->colptrs->clear();
			this->vals->clear();
		}
		void WriteCCSToST(CCSMatrix &matrix, std::string filename)
		{
			std::ofstream macierzST(filename.c_str());
			if(!macierzST)
				throw std::runtime_error("Cannot open output file for ST matrix\n");

			size_t nz = 0;
			for(size_t column_no = 0; column_no < matrix.NumberOfColumns(); column_no++)
				nz += matrix.GetCompressedColumn(column_no)->GetValues()->size();


			macierzST<<matrix.NumberOfRows()<<" "<<matrix.NumberOfColumns()<<" "<<nz<<std::endl;
			for(size_t i=0;i<matrix.NumberOfColumns();i++)
			{
				Matrices::STDoubleMapPtr values = matrix.GetCompressedColumn(i)->GetValues();
				macierzST<<values->size()<<std::endl;
				for(Matrices::STDoubleMapIter iter = values->begin();iter!=values->end();++iter)
					macierzST<<iter->first<<" "<<iter->second<<std::endl;
			}
			macierzST.close();
		}

		void CCSMatrixWriter::ConvertToLists(CCSMatrix &matrix)
		{
			size_t columns =  matrix.NumberOfColumns();
			size_t insertIndex = 0;

			for(size_t column = 0; column < columns; column++)
			{
				CompressedVectorPtr v = matrix.GetCompressedColumn(column);

				for(std::map<size_t, double>::const_iterator iter = v->GetValues()->begin(); iter != v->GetValues()->end(); iter++)
				{
					rowind->push_back(iter->first);
					vals->push_back(iter->second);
				}

				colptrs->push_back(insertIndex);

				insertIndex = vals->size();
			}
			colptrs->push_back(vals->size());
		}

		void WriteToSingleFile(CCSMatrixPtr pMatrix, const std::string &filename)
		{
			// first count NZ
			size_t nz = 0;
			for(size_t column_no = 0; column_no < pMatrix->NumberOfColumns(); column_no++)
				nz += pMatrix->GetCompressedColumn(column_no)->GetValues()->size();

			std::ofstream file(filename.c_str());
			if(!file)
				throw filesystem_error( "Cannot open file for writing: " + filename);

			file << pMatrix->NumberOfRows() << " "  << pMatrix->NumberOfColumns() << " " << nz << std::endl;

			for(size_t column_no = 0; column_no < pMatrix->NumberOfColumns(); column_no++)
			{
				std::map<size_t, double>* vals = pMatrix->GetCompressedColumn(column_no)->GetValues();
				for(std::map<size_t, double>::iterator iter = vals->begin(); iter != vals->end(); iter++)
				{
					file << iter->first << " " << iter->second << " ";
					if(iter->second==0)
						LOG4CXX_WARN(logger,"Warning: inserted value 0 into output file!");
				}
				file << std::endl;
			}

			file.close();
		}
	}//namespace IO
}//namespace Matrices

