/*
    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 "arch_headers.h"
#include "MatrixSaver.h"
#include "Config.h"

#define FEATURE_ENTROPY "entropy"
#define FEATURE_TF "tf"
#define FEATURE_GLOBAL_TF "global-tf"
#define FEATURE_DESC_ID "desc_id"
#define FEATURE_DESC "desc"
#define FEATURE_NZ "nz"

namespace me_architect
{

	void MatrixSaver::SaveToSuperMatrix ( Matrices::CRSMatrixPtr crs, size_t unitscount)
	{
		using namespace Matrices;
		CCSMatrix *ccs = new CCSMatrix("data",0,0);
		crs->Clone(ccs);
		pCCS = CCSMatrixPtr(ccs);
		pCRS = crs;

		PrepareFeatures();

		Config *c = Config::GetInstance();

		SuperMatrixPtr supermatrix( new SuperMatrix( c->m_sMatrixName, pCCS, pCRS, 
					row_features, column_features, unitscount, c->m_sCorpusInfo) ) ;

		Matrices::IO::SuperMatrixWriter writer;
		std::cout << "Saving matrix...\n";
		writer.Write(supermatrix, c->m_sWorkdir);

		pCCS.reset();
		pCRS.reset();
		row_features.reset();
		column_features.reset();
	}

	void MatrixSaver::PrepareFeatures()
	{
		LexicalUnits::UnigramDictionary *dict = LexicalUnits::UnigramDictionary::GetInstance();		
		Config *config = Config::GetInstance();
		// row features...
		row_features = Matrices::FeatureVectorPtr( new Matrices::FeatureVector() );
		for( size_t row_no = 0; row_no < pCRS->NumberOfRows(); row_no++)
		{
			Matrices::CompressedVectorPtr v = pCRS->GetCompressedRow(row_no);
			double entropy = Measures::CountVectorEntropy( *v );
			size_t nz = v->GetValues()->size();
			size_t tf = (size_t) Measures::CountVectorSum( *v );
			LexicalUnits::LexicalUnitPtr pUnit = (config->m_vLexicalUnits)[ config->rowLU[ row_no ] ];
			size_t TF = dict->GetCount(pUnit);
			std::string  word = Corpus::CWordDictionary::GetInstance()->GetAt(pUnit->GetBaseId() );
			std::map<size_t, std::string>::iterator find = config->rowToFlex.find(row_no);
			if(find != config->rowToFlex.end() )
				word = find->second + ":" + word;
			row_features->push_back( Matrices::Feature(word, nz, tf, TF, entropy) ) ;
			if( row_no % 100 == 0)
				std::cout << "Counting row features... " << row_no << " / " << pCRS->NumberOfRows() << std::endl;
		}
		// column features...
		column_features = Matrices::FeatureVectorPtr( new Matrices::FeatureVector() );
		for( size_t column_no = 0; column_no < pCCS->NumberOfColumns(); column_no++)
		{
			Matrices::CompressedVectorPtr v = pCCS->GetCompressedColumn(column_no);
			double entropy = Measures::CountVectorEntropy( *v );
			size_t nz = v->GetValues()->size();
			size_t tf = (size_t) Measures::CountVectorSum( *v );
			LexicalUnits::LexicalUnitPtr pUnit = (config->m_vLexicalUnits)[ config->columnLU[ column_no ] ];
			size_t TF = dict->GetCount(pUnit);
			std::string word = Corpus::CWordDictionary::GetInstance()->GetAt(pUnit->GetBaseId() );
			std::map<size_t, std::string>::iterator find = config->columnToFlex.find( column_no );
			if(find != config->columnToFlex.end() )
				word = find->second + ":" + word;
			column_features->push_back( Matrices::Feature(word, nz, tf, TF, entropy) ) ;
			if( column_no % 100 == 0)
				std::cout << "Counting column features... " << column_no << " / " << pCCS->NumberOfColumns() << std::endl;
		}

	}
}
