#include "ResourceDirectory.h"
#include "ResourceDirectoryEntry.h"
#include "ResourceDataEntry.h"

#include <iostream>

ResourceDirectory::ResourceDirectory( PIMAGE_RESOURCE_DIRECTORY prd ) 
	: _rdDir(*prd), writtenAt(0)
{
	_rdDir.NumberOfIdEntries = 0;
	_rdDir.NumberOfNamedEntries = 0;
}

void ResourceDirectory::AddEntry( ResourceDirectoryEntry* entry )
{
	int i = 0;
	
	if (entry->HasName()) {
		WCHAR* entryName = entry->GetName();
		
#if 0
		cout << "Adding entry \"" << entryName << "\" ";
#endif		

		for (i = 0; i < _rdDir.NumberOfNamedEntries; i++) {
			WCHAR* name = _entries[i]->GetName();
			int cmp = wcscmp(name, entryName);
			delete [] name;
			if (cmp == 0) {
				delete [] entryName;
				return;
			}
			if (cmp > 0)
				break;
		}
		delete [] entryName;
		_rdDir.NumberOfNamedEntries++;
		
	} else {
		
#if 0
		cout << "Adding entry " << entry->GetId() << " ";
#endif		

		for (i = _rdDir.NumberOfNamedEntries; i < _rdDir.NumberOfNamedEntries + _rdDir.NumberOfIdEntries; i++)
		{
			if (_entries[i]->GetId() == entry->GetId())
				return;
			if (_entries[i]->GetId() > entry->GetId())
				break;
		}
		_rdDir.NumberOfIdEntries++;
	}
	
	//cout << "at position " << i << endl;
	
	_entries.insert(_entries.begin() + i, entry);
}

int ResourceDirectory::Find( WCHAR* name )
{
	if (IS_INTRESOURCE(name))
		return Find((WORD)(DWORD)name);
	else
		if (name[0] == '#')
			return Find(WORD(atoi((PCHAR)name + 1)));
	
	for (UINT i = 0; i < _entries.size(); i++)
	{
		if (_entries[i]->HasName())
			continue;

		WCHAR* entryName = _entries[i]->GetName();
		int cmp = wcscmp(name, entryName);
		delete [] entryName;

		if (!cmp)
			return i;
	}

	return -1;
}

int ResourceDirectory::Find( WORD Id )
{
	for (UINT i = 0; i < _entries.size(); i++)
	{
		if (_entries[i]->HasName())
			continue;

		if (Id == _entries[i]->GetId())
			return i;
	}
	return -1;
}

DWORD ResourceDirectory::GetSize()
{
	DWORD size = sizeof(IMAGE_RESOURCE_DIRECTORY);
	for (UINT i = 0; i < _entries.size(); i++) {
		size += sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY);
		if (_entries[i]->HasName())
			size += sizeof(IMAGE_RESOURCE_DIR_STRING_U) + (_entries[i]->GetNameLength() + 1) * sizeof(WCHAR);
		if (_entries[i]->IsDataDirectory())
			size += _entries[i]->GetSubDirectory()->GetSize();
		else {
			DWORD aligned = _entries[i]->GetDataEntry()->GetSize();
			ALIGN(aligned, 8);
			size += sizeof(IMAGE_RESOURCE_DATA_ENTRY) + aligned;
		}
	}
	
	return size;
}

void ResourceDirectory::Destroy()
{
	for (UINT i = 0; i < _entries.size(); i++) {
		if (_entries[i]->IsDataDirectory()) {
			_entries[i]->GetSubDirectory()->Destroy();
			delete _entries[i]->GetSubDirectory();
		} else {
			delete _entries[i]->GetDataEntry();
		}
	}
}
