/*
 * hier_cluster.h
 *
 *  Created on: Nov 22, 2014
 *      Author: qimao
 */

#ifndef HIER_CLUSTER_H_
#define HIER_CLUSTER_H_
#include <vector>
#include <string>
#include <unordered_set>
#include <armadillo>

#include "params.h"
#include "sparse_matrix.h"
#include "flat_cluster.h"

using namespace arma;

class TreeNode
{
public:
	std::string name;
	float diameter;
	std::unordered_set<int> cluster;
	std::vector<TreeNode> children;

	TreeNode(){diameter = 0.0;}
	TreeNode(std::string name_):name(name_){diameter = 0.0;}
	virtual ~TreeNode(){  }

	std::string print_tree(int level);

	/* output structured format of trees to output device*/
	void print_tree(std::ostream &out);
	void get_struct_clusters(std::string path, std::vector<std::string> &paths, std::vector<std::unordered_set<int> > & clusters);

	/* obtain sets of the leaf nodes in the depth-first traverse*/
	void get_clusters(std::vector<std::unordered_set<int> > & clusters);
};

class DivisiveHierCluster {
private:
	TreeNode root;
	ActiveFlatCluster & base_cluster;
	Params & params;

public:
	DivisiveHierCluster(ActiveFlatCluster & flat_cluster, Params &params_): root("root"), base_cluster(flat_cluster),params(params_){}
	virtual ~DivisiveHierCluster(){}

	void cluster(SeqSparseMatrix &smat);
	void depth_first_cluster(TreeNode &root, SeqSparseMatrix &smat, uvec & indices);
	void print_hier_tree(std::ostream &out){ root.print_tree(out);}
	void get_clusters(std::vector<std::unordered_set<int> > & clusters) { return this->root.get_clusters(clusters);}
};

#endif /* HIER_CLUSTER_H_ */
