string
HuffmanEncoder::decodeBits(vector<bool> bits, vector<string> huffmanMap)
{
    HuffmanTree *tree = HuffmanEncoder::huffmanTreeFromMap(huffmanMap);

    vector<string> map = HuffmanEncoder::huffmanEncodingMapFromTree(tree);
    HuffmanEncoder::writeEncodingMapToFile(map, "encmap.map");

    HuffmanNode *n = tree->GetRoot();
    ostringstream result{};
    uint64_t last_index = 0;
    string stack;
    int num_decoded = 0;

    //tree->Print();

    for (auto it = bits.begin(); it != bits.end(); ++it) {
        bool bit = *it;
        if (bit == false) {
            stack += "0";
            n = ((HuffmanInternalNode*)n)->GetLeftChild();
        }
        else {
            stack += "1";
            n = ((HuffmanInternalNode*)n)->GetRightChild();
        }
        if (n->IsLeaf()) {
            result << ((HuffmanLeafNode*)n)->GetValue();
            num_decoded++;
            n = tree->GetRoot();
            stack = "";
        }
        last_index++;
    }

    /* TODO: perhaps the priority queue is different for each? That might
     * explain it. Compare frequencies, that can't be wrong. Issue is we have
     * different huffman maps on each run. Although, that might not be a problem
     * on write. The files are slightly different, make sure it's writing to a
     * good offset. Maybe try writing/reading garbage from that spot or
     * something, print out the first few chars, idk. Print where the offsets
     * and such are. Figure out exactly what is going where and if the way it's
     * getting compressed/decompressed differently is a problem. */


    return result.str();
}
HuffmanTree*
HuffmanEncoder::huffmanTreeFromMap(vector<string> huffmanMap)
{
    //Generates a Huffman Tree based on the supplied Huffman Map.Recall that a
    //Huffman Map contains a series of codes(e.g. 'a' = > 001).Each digit(0, 1)
    //in a given code corresponds to a left branch for 0 and right branch for 1.

    HuffmanTree *tree = new HuffmanTree(new HuffmanInternalNode(NULL, NULL));

    for (int i = 0; i < 256; i++) {
        char c = (char) i;
        string code = huffmanMap[i];
        if (code.length() == 0)
            continue;
        HuffmanInternalNode *n = (HuffmanInternalNode*)tree->GetRoot();

        for (unsigned int j = 0; j < code.length() -1; ++j) {
            if (code[j] == '0') {
                if (n->GetLeftChild() != NULL) {
                    n = (HuffmanInternalNode*) n->GetLeftChild();
                }
                else {
                    n->SetLeftChild(new HuffmanInternalNode(NULL, NULL));
                    n = (HuffmanInternalNode*) n->GetLeftChild();
                }
            }
            else {
                if (n->GetRightChild() != NULL) {
                    if (n->IsLeaf()) {
                        //tree->Print();
                        exit(1);
                    }
                    n = (HuffmanInternalNode*) n->GetRightChild();
                }
                else {
                    n->SetRightChild(new HuffmanInternalNode(NULL, NULL));
                    n = (HuffmanInternalNode*) n->GetRightChild();
                }
            }
        }
        c = code[code.length() -1];
        if (c == '0') {
            n->SetLeftChild(new HuffmanLeafNode((char)i, 0));
        }
        else {
            n->SetRightChild(new HuffmanLeafNode((char)i, 0));
        }
    }

    //printf("Tree created from map:\n");
    //tree->Print();

    return tree;
}
void FileCompress::Uncompress(const char* filename)
{
	HuffmanTree ht;
	int size = 0;
	//从配置文件中获取字符信息
	string filenameconfig = filename;
	filenameconfig += ".config";

	FILE* fout = fopen(filenameconfig.c_str(),"r");
	assert(fout);
	unsigned char ch = fgetc(fout);
	long long sum = 0;
	while (!feof(fout))
	{
		_infos[ch]._ch = ch;
		size++;
		char num = fgetc(fout);
		num = fgetc(fout);
		_infos[ch]._count = num - '0';
		sum += _infos[ch]._count;
		ch = fgetc(fout);
		ch = fgetc(fout);
	}
	fclose(fout);
	//建树
	CharInfo invaild;
	//ReadConfig(filename, _infos);
	ht.CreateTree(_infos, size,invaild);

	//从压缩文件取值遍历
	string filenamecom = filename;
	filenamecom += ".com";
	FILE* fin = fopen(filenamecom.c_str(),"r");
	assert(fin);

	string filenameuncom = filename;
	filenameuncom += ".uncom";

	fout = fopen(filenameuncom.c_str(), "w");
	assert(fout);
	HuffmanTreeNode<CharInfo>* temp = ht.GetRoot();
	ch = fgetc(fin);
	int count = 0;
	unsigned int t = 1;
	while ( !feof(fin))//sum != 0)
	{
		int x = 0;
		for (int i = 7; i >= 0; i--)
		{
			x = ch & (t << 7);
			if ((char)ch == EOF)
			{
				cout << 1;
			}
			ch <<= 1;
			if (x == 0)
				temp = temp->_left;
			else if (x == 0x80)
				temp = temp->_right;
			if (temp->_left == NULL && temp->_right == NULL)
			{
				fputc(temp->_weight._ch, fout);
				//sum--;
				cout << temp->_weight._ch;
				temp = ht.GetRoot();
				x = 0;
			}
		}
		ch = fgetc(fin);
	}
	fclose(fin);
	fclose(fout);
}
void FileCompress::Compress(const char* filename)
{
	HuffmanTree mh;
	int size = Get_infos_Com(filename);
	//建树
	CharInfo invaild;
	mh.CreateTree(_infos, size,invaild);
	//编码
	string code;
	GenerateHuffmanCode(mh.GetRoot(), code);

	//配置文件
	string filenameConfig = filename;
	filenameConfig += ".config";
	
	FILE* fout = fopen(filenameConfig.c_str(), "wb");

	assert(fout);
	for (int i = 0; i < 256; i++)
	{
		if (_infos[i]._count != 0)
		{
			fputc(_infos[i]._ch, fout);
			fputc(',', fout);
			fputc(_infos[i]._count+'0',fout);
			fputc('\n',fout);
		}
	}
	fclose(fout);
	//WriteConfig(filename);
	FILE* fin = fopen(filename, "r");
	unsigned char ch = fgetc(fin);

	string filenamecom = filename;
	filenamecom += ".com";

	fout = fopen(filenamecom.c_str(), "w+");
	assert(fout);
	
	unsigned char value = 0;
	int pos = 7;

	while (!feof(fin))
	{
		if (ch == '\r')
		{
			ch = fgetc(fout);
			if (ch != '\n')
			{
				fseek(fout, -1, SEEK_CUR);
			}
		}
		string& code = _infos[ch].code;
		int d = 0;
		for (int i = 0; i < code.size(); i++)
		{
			value <<= 1;
			if ((code[i] - '0') & (1))
			{
				value |= 1;
			}
			else
			{
				value |= 0;
				d = 1;
			}
			pos--;

			if (pos == -1)
			{
				fputc(value, fout);
				if (d = 0)
				{
					cout << 1;
				}
				value = 0;
				d = 0;
				pos = 7;
			}
		}
		ch = fgetc(fin);
	}
	if (pos != -1)
	{
		for (int i = 0; i <= pos; i++)
		{
			value <<= 1;
		}
		fputc(value, fout);
	}
	fclose(fin);
	fclose(fout);
}