// Huffman.cpp : Defines the entry point for the console application.
//

#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <fstream>

#include "DataSet.h"
#include "HElement.h"
#include "DataCharString.h"


HElement * huffman_f(std::vector <DataSet> in){

	std::vector<DataSet>::iterator it;
	HElement* t;
	DataSet * first;
	DataSet * second ;
	int i;

	if (in.size() == 1)
			return new HElement ((in[0]));
	if (in.size() == 0)
			return NULL;

	for ( i = in.size() - 1 ;  i>0 ; --i){

		std::sort(in.begin(), in.begin() + i + 1  ,DataSet::order_dec);

		second = &(in[i]);
		first = &(in[i - 1]);

		t = new HElement (false, * first, * second );
		in.erase(in.begin() + i - 1);
		in.insert(in.begin() + i - 1 ,DataSet (0,t->getleft_p()->getcore().getfrequency() + t->getright_p()->getcore().getfrequency(),t));

	}

	return (*(in.begin())).gett_list();
}


void huffman_p (HElement * list, std::vector <DataCharString> * vect , std::string in_s){

	if (list != NULL){
		if (list->isconcrete()){
			DataCharString * t;
			t = new DataCharString (list->getcore().getcharacter(),in_s );
			(*vect).push_back(*t);
			free(t);
		}else{
			huffman_p (list->getleft_p(),vect, in_s + "0");
			huffman_p (list->getright_p(),vect,in_s + "1");
		}
	}
}


std::vector<DataSet> & read_data (char* file){

	try {
		std::fstream f (file ,std::ios_base::in );

		if (f.good()){
			std::vector<DataSet> *ridden_data = new std::vector<DataSet> ();
			DataSet * t;
			std::vector<DataSet>::iterator it;
			for (char input = f.get(); f.good() ; input = f.get() ){
				it = std::find((*ridden_data).begin(),(*ridden_data).end(), input );
				if ((*ridden_data).size() == 0 || it==(*ridden_data).end()){
					t = new DataSet (input,1);
					(*ridden_data).push_back (*t);
					free(t);
				}else{
					(*it).increment_frequency();
				}
			}
			return *ridden_data;


		}else{
			std::cout << "Error reading file" << std::endl;
			exit(-1);
		}
	}
	catch ( std::ios_base::failure & e){
		std::cout << "Error reading file" << std::endl;
		exit(-1);

	}


}



