#include "HuffmanEncoder.h"

#include "Tree.h"

#include <unordered_map>
#include <queue>
#include <tuple>
#include <iostream>

void HuffmanEncoder::encode(const HuffmanEncoder::DataStream& stream)
{
	std::unordered_map<unsigned char, unsigned> counts;
	for (auto c : stream)
	{
		counts[c]++;
	}

	using CountPair = std::pair<unsigned char, unsigned>;
	auto cmp = [](CountPair left, CountPair right)
		{
			return left.second > right.second;
		};
	std::priority_queue<CountPair, std::vector<CountPair>, decltype(cmp)> q(cmp);
	for (const auto& entry : counts)
	{
		q.push({entry.first, entry.second});
	}

	NodePtr<CountPair> lastNode;
	while(!q.empty())
	{
		const auto charData = q.top();
		auto characterNode = std::make_unique<Node<CountPair> >(charData);
		q.pop();

		if (!lastNode)
		{
			const auto rightCharData = q.top();
			auto rightCharacterNode = std::make_unique<Node<CountPair> >(rightCharData);
			q.pop();

			const auto sum = charData.second + rightCharData.second;
			CountPair data{0, sum};
			auto midNode = std::make_unique<Node<CountPair> >(data);

			midNode->addChild(std::move(characterNode));
			midNode->addChild(std::move(rightCharacterNode));
			lastNode = std::move(midNode);
		}
		else
		{
			const auto sum = lastNode->getData().second;
			CountPair data{0, sum};
			auto midNode = std::make_unique<Node<CountPair> >(data);

			if (charData.second < lastNode->getData().second)
			{
				midNode->addChild(std::move(lastNode));
				midNode->addChild(std::move(characterNode));
			}
			else
			{
				midNode->addChild(std::move(characterNode));
				midNode->addChild(std::move(lastNode));
			}
			lastNode = std::move(midNode);
		}
	}

	Tree<CountPair> tree;
	tree.addRootNode(std::move(lastNode));

	//using TableEntry = std::tuple<>


	std::cout << "********" << std::endl;
}
