#include "dexibuild.hpp"

// some externally defined handler functions
void buildDWORLD(TiXmlElement* pRoot, deString2 inputFileName);

DexiBuilder::DexiBuilder()
{
	RegisterDexiHandler("dworld", buildDWORLD);
}

DexiBuilder::~DexiBuilder()
{
}

void DexiBuilder::RegisterDexiHandler(const char* targetName, dexiDocHandler h)
{
	if (!h)
		throw dexiException("Invalid handler");
	m_Handlers[targetName] = h;
}

void DexiBuilder::loadBatch(deString2 batchDir, bool doSubDirs)
{
	IdeFileSystem* pFS = NULL;
	void* searchhandle = NULL;
	try
	{
		batchDir.Replace('\\', '/');
		deFileProperties props;
		pFS = IdeFileSystem_CreateFSReal();
		if (!pFS)
		{
			throw dexiException("Error creating filesystem");
		}
		if (!pFS->SetDirectory(batchDir.const_str()))
		{
			deString error;
			error.Format("Error setting directory: '%s'", batchDir.const_str());
			throw dexiException(error);
		}
		searchhandle = pFS->FindFirst("*.dexi", &props);
		if (searchhandle)
		{
			do
			{
				deString2 filename(batchDir);
				filename += props.Filename;
				loadFile(filename);
			} while(pFS->FindNext(searchhandle, &props));
			pFS->FindEnd(searchhandle);
		}
		if (doSubDirs)
		{
			deString2 str_dot(".");
			deString2 str_dotdot("..");
			searchhandle = pFS->FindFirst("*", &props);
			if (searchhandle)
			{
				do
				{
					if (!(props.Flags & deFile_Directory))
						continue;
					if (str_dot == props.Filename || str_dotdot == props.Filename)
						continue;
					deString2 filename(batchDir);
					filename += props.Filename;
					filename += "/";
					loadBatch(filename, true);
				} while(pFS->FindNext(searchhandle, &props));
				pFS->FindEnd(searchhandle);
			}
		}
		pFS->Release();
	}
	catch (dexiException e)
	{
		if (searchhandle && pFS)
			pFS->FindEnd(searchhandle);
		if (pFS)
			pFS->Release();
		throw e;
	}
}

void DexiBuilder::loadFile(deString2 filename)
{
	TiXmlDocument* pXmlDoc = NULL;
	try
	{
		LogExportMsg(Log_Message, "Loading XML file: '%s'\n", filename.const_str());
		pXmlDoc = new TiXmlDocument(filename.const_str());
		if (!pXmlDoc)
		{
			throw dexiException("Error creating XML document\n");
		}
		if (!pXmlDoc->LoadFile())
		{
			deString error;
			error.Format("Error loading XML document\nTinyXML error description: %s\nLocation: (%d,%d)", 
				pXmlDoc->ErrorDesc(), 
				pXmlDoc->ErrorRow(), 
				pXmlDoc->ErrorCol());
			throw dexiException(error);
		}
		
		handleDoc(pXmlDoc, filename);
		
		delete pXmlDoc;
	}
	catch(dexiException e)
	{
		delete pXmlDoc;
		LogExportMsg(Log_Error, "============================\n");
		LogExportMsg(Log_Error, "Fatal Error: %s\n", e.what.const_str());
		LogExportMsg(Log_Error, "============================\n");
	}
}

void DexiBuilder::handleDoc(TiXmlDocument* pDoc, deString2 inputFileName)
{
	TiXmlElement* pRootElem = pDoc->RootElement();
	deString2 targetName = pRootElem->Attribute("target");

	handlermap::iterator it = m_Handlers.find(targetName);
	if (it == m_Handlers.end())
	{
		LogExportMsg(Log_Error, "Unknown target: '%s'\n", targetName.const_str());
	}
	else
	{
		LogExportMsg(Log_Message, "Building for target: '%s'\n", targetName.const_str());
		dexiDocHandler handler = it->second;
		handler(pRootElem, inputFileName);
	}	
}

