/*
    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 "../comparator_stdheaders.h"
#include "Comparator.h"

namespace smartcomparator
{
	namespace compare
	{
		Comparator::Comparator(Matrices::SuperMatrixPtr matrix, boost::shared_ptr<CompareFunction> cf, size_t min_nz, size_t minTF, size_t min_tf )
			: m_Matrix(matrix),
			m_CompareFunction(cf),
			m_stMinGlobalTF(minTF),
			m_stMinLocalTF(min_tf),
			m_stMinNZ(min_nz)
		{		
		}

		Comparator::~Comparator(void)
		{
		}

		std::multimap<double, size_t> Comparator::FindSimiliar(size_t id, size_t n) 
		{

			std::multimap<double, size_t> allTerms, desiredTerms;		
			size_t tf = (*m_Matrix->GetRowFeatures())[id].GetTermFrequency();
			size_t TF = (*m_Matrix->GetRowFeatures())[id].GetGlobalTermFrequency();
			size_t nz_count = (*m_Matrix->GetRowFeatures())[id].GetNZ();
			if( nz_count < m_stMinNZ || TF < m_stMinGlobalTF || tf < m_stMinLocalTF )
				return allTerms;

			//najpierw trzeba porównać termin szukany z wszystkimi z macierzy...
			FindAllSimiliar(id,allTerms);

			//teraz trzeba obciąć wszystkie terminy do n wymaganych

			std::multimap<double, size_t>::reverse_iterator rfirst(allTerms.end());
			std::multimap<double, size_t>::reverse_iterator rlast(allTerms.begin());
			if(rfirst == rlast)
				return desiredTerms;
			size_t numberInserted = 0;
			do
			{
				if( rfirst->first > m_CompareFunction->MinValue())
				{
					desiredTerms.insert(*rfirst);
					numberInserted++;
				}
				rfirst++;
			}while(rlast!=rfirst && numberInserted < n);

			return desiredTerms;
		}

		void Comparator::FindAllSimiliar(size_t id, std::multimap<double, size_t>& allTerms)
		{
			size_t rows = m_Matrix->NumberOfRows();

			//int i =0;
			for(size_t row = 0; row < rows; row++)
			{
				if(row == id)
					continue;
				size_t tf = (*m_Matrix->GetRowFeatures())[row].GetTermFrequency();
				size_t TF = (*m_Matrix->GetRowFeatures())[row].GetGlobalTermFrequency();
				size_t nz_count = (*m_Matrix->GetRowFeatures())[row].GetNZ();
				if( nz_count < m_stMinNZ || TF < m_stMinGlobalTF || tf < m_stMinLocalTF )
					continue;

				double sim = m_CompareFunction->Compare(id, row);
				allTerms.insert( std::pair<double, size_t> ( sim, row ) );
			}
		}

		size_t Comparator::TOEFLQuestion(size_t termId, std::set<size_t> &possibleAnwsers)
		{
			size_t anwser = 0;

			double closest = -99999.9;

			for(std::set<size_t>::iterator testTermId = possibleAnwsers.begin(); 
				testTermId != possibleAnwsers.end(); testTermId++)
			{

				double similarity = m_CompareFunction->Compare(termId, *testTermId);
				size_t tf = (*m_Matrix->GetRowFeatures())[*testTermId].GetTermFrequency();
				size_t TF = (*m_Matrix->GetRowFeatures())[*testTermId].GetGlobalTermFrequency();
				size_t nz = (*m_Matrix->GetRowFeatures())[*testTermId].GetNZ();
				if( nz < m_stMinNZ || TF < m_stMinGlobalTF || tf < m_stMinLocalTF )
					continue;
				if(similarity > closest)
				{
					closest = similarity;
					anwser = *testTermId;
				}
			}

			return anwser;
		}


	}
}
