/*
    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 "vector_extractor.h"
#include "options.h"

int main(int ac, char *av[])
{
	Matrices::init_logging();
	try
	{
		vector_extractor::Options options(ac,av);
		vector_extractor::VectorExtractor ve(options.GetParams() );
		ve.Start();
	}
	catch(std::exception &e)
	{
		std::cerr << "Error: " << e.what() << std::endl;
		return -1;
	}
	return 0;
}

namespace vector_extractor
{
	VectorExtractor::VectorExtractor(const Params &p) : m_Params(p)
	{
	}

	void VectorExtractor::Start()
	{
		LoadWords();
		if(!m_Params.m_bRows)
			ExtractColumns();
		else
			ExtractRows();
	}

	void VectorExtractor::ExtractColumns()
	{
		Matrices::SuperMatrixPtr pMatrix = Matrices::IO::LoadSuperMatrix(m_Params.m_sMatrixDir, m_Params.m_sMatrixName, true, false);

		std::ofstream file(m_Params.m_sOutName.c_str() );


		std::cout << "Extracting columns from matrix " << pMatrix->GetName() << std::endl;


		file << "row_label";
		for(size_t word_no = 0; word_no < m_vWords.size(); word_no++)
		{
			Matrices::CompressedVectorPtr pColumn = pMatrix->GetColumn( m_vWords[word_no] );
			if( pColumn == NULL ){
				std::cout << "No word in matrix: "<< m_vWords[word_no] << std::endl;
				continue;
			}
			file << ";" << m_vWords[word_no]; 
		}
		file << std::endl;

		for(size_t row_no = 0; row_no < pMatrix->NumberOfRows(); row_no++)
		{
			const std::string & row_word = pMatrix->GetRowFeatures()->operator[](row_no).GetLabel();
			file << row_word;
			for(size_t word_no = 0; word_no < m_vWords.size(); word_no++)
			{
				Matrices::CompressedVectorPtr pColumn = pMatrix->GetColumn( m_vWords[word_no] );
				if( pColumn == NULL ){
					continue;
				}
				file << ";" << (*pColumn)[row_no];
			}
			file << std::endl;
		}
		file.close();

		std::cout << "Extracting columns from matrix " << pMatrix->GetName() << ". OK!" <<std::endl;
	}//	void VectorExtractor::ExtractColumns()

	void VectorExtractor::ExtractRows()
	{
		Matrices::SuperMatrixPtr pMatrix = Matrices::IO::LoadSuperMatrix(m_Params.m_sMatrixDir, m_Params.m_sMatrixName, false, true);

		std::ofstream file(m_Params.m_sOutName.c_str() );


		std::cout << "Extracting rows from matrix " << pMatrix->GetName() << std::endl;


		file << "column_label";
		for(size_t word_no = 0; word_no < m_vWords.size(); word_no++)
		{
			Matrices::CompressedVectorPtr pRow = pMatrix->GetRow( m_vWords[word_no] );
			if( pRow == NULL ){
				std::cout << "No word in matrix: "<< m_vWords[word_no] << std::endl;
				continue;
			}
			file << ";" << m_vWords[word_no]; 
		}
		file << std::endl;

		for(size_t column_no = 0; column_no < pMatrix->NumberOfColumns(); column_no++)
		{
			const std::string & column_word = pMatrix->GetColumnFeatures()->operator[](column_no).GetLabel();
			bool any_non_zero = false;
			for(size_t word_no = 0; word_no < m_vWords.size() && !any_non_zero; word_no++)
			{
				Matrices::CompressedVectorPtr pRow = pMatrix->GetRow( m_vWords[word_no] );
				if( pRow == NULL )
					continue;
				if(pRow->GetValues()->operator [](column_no) > 0 )
					any_non_zero = true;
			}
			if(!any_non_zero)
				continue;
			
			file << column_word;
			for(size_t word_no = 0; word_no < m_vWords.size(); word_no++)
			{
				Matrices::CompressedVectorPtr pRow = pMatrix->GetRow( m_vWords[word_no] );
				if( pRow == NULL )
					continue;
				file << ";" << (*pRow)[column_no];
			}
			file << std::endl;
		}
		file.close();

		std::cout << "Extracting rows from matrix " << pMatrix->GetName() << ". OK!" <<std::endl;
	}//	void VectorExtractor::ExtractColumns()

	void VectorExtractor::LoadWords()
	{
		std::ifstream file( m_Params.m_sWordsFile.c_str() );
		if(!file)
			throw std::runtime_error( "Cannot open file: " + m_Params.m_sWordsFile );

		std::string line;
		while( std::getline(file,line) )
		{
			boost::trim(line);
			if(line.length() )
				m_vWords.push_back(line);
		}

		std::cout << "Loaded " << m_vWords.size() << " words from " << m_Params.m_sWordsFile << std::endl;
	}

}//namespace vector_extractor
