/*
    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.
*/

#ifndef MAIN_CPP
#define MAIN_CPP
#include "matrices_all.h"

void helpMsg(char* av)
{
	std::cout<<"Program computing mean median of rows and filtering values according to it, or given in parameter\n"
			<<"Considers only non-empty rows\n"
			<<"Runtime format: "<<av<<" in_matrix out_matrix [filter_value]\n";
}

int main(int ac, char**av)
{
	Matrices::init_logging();
	if(ac>0 && (strcmp(av[1],"--help")==0))
	{
		helpMsg(av[0]);
		return 1;
	}
	if(ac!=3 && ac!=4)
	{
		helpMsg(av[0]);
		throw std::runtime_error("Invalid number of parameters!\n");
		return -1;
	}
	double meanMedian;
	Matrices::CRSMatrixPtr inMatrix = Matrices::IO::ReadCRSFromSingleFile(av[1],"in_matrix");
	if(ac==3)
	{
		int rowCounter=0;
		double medianSum=0;
		for(size_t i=0;i<inMatrix->NumberOfRows();i++)
		{

			Matrices::STDoubleMapPtr rowValues = inMatrix->GetCompressedRow(i)->GetValues();
			if(rowValues->size()!=0)
			{
				double *valueTable = new double[rowValues->size()];
				int j=0;
				for(Matrices::STDoubleMapIter iter = rowValues->begin();iter!=rowValues->end();++iter)
				{
					valueTable[j++]=iter->second;
				}

				std::sort(valueTable,valueTable+rowValues->size());

				medianSum+= valueTable[rowValues->size()/2];
				rowCounter++;
			}
		}
		meanMedian = medianSum/rowCounter;
	}
	else
		meanMedian = atof(av[3]);

	std::cout<<"Filtering value: "<<meanMedian<<std::endl;


	for(size_t i=0;i<inMatrix->NumberOfRows();i++)
	{

		std::map<size_t, double> m = *(inMatrix->GetCompressedRow(i)->GetValues());
		if(m.size()!=0)
		{
			for(Matrices::STDoubleMapIter iter = m.begin();iter!=m.end();++iter)
			{
				if(iter->second<meanMedian)
					inMatrix->SetCell(0,i,iter->first);

			}
		}
	}
	std::cout<<"Saving filtered matrix"<<std::endl;
	Matrices::IO::WriteToSingleFile(inMatrix,av[2]);
	return 0;
}

#endif // MAIN_CPP
