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

namespace smartcomparator
{
	namespace selectors
	{
		RFFSelector::RFFSelector(Matrices::SuperMatrixPtr superMatrix,size_t TFTreshold, double weightTreshold)
			:Selector(superMatrix)
		{
			this->weightTreshold= weightTreshold;
			this->TFTreshold = TFTreshold;

			PrepareColumnIndices();
			PrepareRowIndices();

		}
		void RFFSelector::PrepareColumnIndices()
		{
			Matrices::FeatureVectorPtr columnFeatures = m_pMatrix->GetColumnFeatures();
			for(int i=0;i<(int)columnFeatures->size();i++)
				if(columnFeatures->at(i).GetGlobalTermFrequency() <TFTreshold)
					columnsToRemove.insert(i);
		}

		bool RFFSelector::CheckIfValueIsRemoved(size_t rowIndex,size_t colIndex)
		{
			// check TF
			if(columnsToRemove.find(colIndex) != columnsToRemove.end())
				return true;

			// check per row data
			std::map<size_t,std::set<size_t> >::iterator finder=indicesToRemove.find(rowIndex);
			if(finder!=indicesToRemove.end())
				if((finder->second).find(colIndex) != (finder->second).end())
					return true;

			return false;
		}

		void RFFSelector::PrepareRowIndices()
		{
			using namespace Matrices;
			Matrices::FeatureVectorPtr row_features = m_pMatrix->GetRowFeatures();
			Matrices::FeatureVectorPtr col_features = m_pMatrix->GetColumnFeatures();

			weights::MIWeight weighter(m_pMatrix);
			for(int i=0;i<(int)m_pMatrix->NumberOfRows();i++)
			{

				CompressedVector rowCopy (*m_pMatrix->GetRow(i));

				STDoubleMapPtr values = rowCopy.GetValues();

				std::set<size_t> newFilteredIndices, oldFilteredIndices;
				for(STDoubleMapIter iter = values->begin(); iter != values->end(); ++iter)
				{
					newFilteredIndices.insert(iter->first);
					oldFilteredIndices.insert(iter->first);
				}

				weighter.Weight(i,&rowCopy,newFilteredIndices);

				indicesToRemove.insert( std::make_pair(i, std::set<size_t> () ) );
				std::set<size_t>  &currentIndicesToRemove = indicesToRemove[i];

				for(std::set<size_t>::iterator iter2=oldFilteredIndices.begin();iter2!=oldFilteredIndices.end();++iter2)
				{
					STDoubleMap::iterator find = values->find(*iter2);
					if(find == values->end() || find->second < weightTreshold){
						currentIndicesToRemove.insert(*iter2);
					}
					}

			}
		}

		RFFSelector::~RFFSelector()
		{
			// nothing
		}

		void RFFSelector::SelectBestFeatures(size_t rowIndex,const std::set<size_t> &filteredIndices, std::set<size_t> &out)
		{
			std::map<size_t,std::set<size_t> >::iterator finder=indicesToRemove.find(rowIndex);

			for(std::set<size_t>::iterator iter2=filteredIndices.begin();iter2!=filteredIndices.end();++iter2)
			{
				if(columnsToRemove.find(*iter2) != columnsToRemove.end())
					out.insert(*iter2);

				else if(finder!=indicesToRemove.end() && ((finder->second).find(*iter2) !=finder->second.end()))
					out.insert(*iter2);
			}

		}
	}
}
