/*
    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 <boost/shared_ptr.hpp>
#include <boost/filesystem.hpp>
#include "Kmeans.h"
#include "Options.h"
#include "zscores.h"

using namespace Matrices;
using namespace smartcomparator::compare;
using namespace clustering::kmeans;
using namespace clustering::zscores;
using namespace std;

void SaveClutoFile(const Kmeans & kmeans, string output_file, ZScores & zscores);

int main(int argc, char **argv)
{
	Options opt(argc, argv);

	Params params = opt.GetParams();

	SuperMatrixPtr matrix = IO::LoadSuperMatrix(params.matrix_dir, params.matrix_name, false, true);

	CompareFunctionPtr fun;

	if (params.sim_function != "none")
		fun = FunctionFactory::CreateFunction(params.sim_function, matrix);
	else
		fun = FunctionFactory::CreateFunction("cmp(simfunction=cosine())", matrix);

	Kmeans k(params.clusters_no, matrix, fun,  params.seed, params.epsilon);

	k.StartClustering();

	ZScores zscores(k.GetClusters(), fun);

	SaveClutoFile(k, params.output_file, zscores);

	return 0;
}

void SaveClutoFile(const Kmeans & kmeans, string output_file, ZScores & zscores)
{
	using namespace boost::filesystem;

	ofstream out_stream(output_file.c_str());
	if(!out_stream)
		throw runtime_error("Error writing to file " + output_file);

	//Not working. Why?
	//std::copy(kmeans.GetClusters().begin(), kmeans.GetClusters().end(), std::ostream_iterator<size_t>(out_stream, "\n"));

	for(size_t row = 0; row < kmeans.GetClusters().size(); ++row)
		out_stream << kmeans.GetClusters()[row] << " " << zscores.GetInternalZScore(row) << " " << zscores.GetExternalZScore(row) << endl;

	out_stream.close();
}
