/*
    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 "kbestcounter.h"

namespace kbestd{

KBestCounterError::KBestCounterError(const std::string &what)
	: std::runtime_error(what)
{

}

std::string KBestCounterError::info() const{
	return what();
}
KBestCounter::KBestCounter()
{
	// noop?
}

KBestCounter::kbestvec KBestCounter::generate_kbest(
	const std::string &matrix_path, const std::string &msr_str,
	const std::string &word,  size_t k)
{
	try{
		if(matrix_path != matrix_path_){
			msr_str_ = "";
			msr_.reset();
			msr_ = smartcomparator::compare::CompareFunctionPtr();
			matrix_.reset();
			load_matrix(matrix_path);
		}
	}catch(std::runtime_error &e){
		throw KBestCounterError(std::string("Problem with loading matrix: ") + e.what() );
	}

	try{
		if(msr_str.size() == 0)
			throw KBestCounterError(std::string("Empty msr are not allowed!"));
		if(msr_str != msr_str_){
			msr_.reset();
			msr_str_ = "";
			msr_ = smartcomparator::compare::FunctionFactory::
					CreateFunction(msr_str, matrix_);
			msr_str_ = msr_str;
		}
	}catch(std::runtime_error &e){
		throw KBestCounterError(std::string("Problem with creating msr: ") + e.what() );
	}

	size_t row = matrix_->GetRowIndex(word);
	size_t rows = matrix_->NumberOfRows();
	if(row > rows)
	{
		std::stringstream ss;
		ss << "Word " << word << " is not in matrix!";
		throw KBestCounterError(ss.str().c_str());
	}


	std::multimap<double, size_t> simmap;

	for(size_t row_no = 0; row_no < rows ; ++row_no)
	{
		if(row_no == row)
			continue;
		double sim = msr_->Compare(row, row_no);
		simmap.insert( std::pair<double,size_t>(sim, row_no));
	}

	kbestvec vec;

	Matrices::FeatureVectorPtr features = matrix_->GetRowFeatures();
	size_t found = 0;
	for(std::multimap<double, size_t>::reverse_iterator riter = simmap.rbegin();
		riter != simmap.rend() && found < k; riter++)
	{
		found++;
		double sim = riter->first;
		if (sim < 0.000001)
			break;
		vec.push_back( std::make_pair(
							(*features)[riter->second].GetLabel(),
							sim) );
	}

	return vec;
}


void KBestCounter::release_mem()
{
	msr_.reset();
	msr_str_ = "";
	matrix_.reset();
	matrix_path_ = "";
}

void KBestCounter::load_matrix(const std::string &mp)
{
	std::string str = mp;
	char last_char = str[ str.length() -1 ];
	if(last_char == '\\' || last_char == '/')
		str = str.substr(0, str.length() -1 );
	boost::filesystem::path p(str);
	p.normalize();
	std::string matrix_name = p.filename().c_str();
	std::string matrix_dir = p.branch_path().string();
	matrix_ = Matrices::IO::LoadSuperMatrix(matrix_dir, matrix_name, false, true);
	matrix_path_ = str;
}

} // ns kbestd
