GameMap::UniquePtr TiledMapParser::parse()
{
	using namespace Poco;

	loadMapImages(fileInfo);
	
	ifstream in(Constants::MapPath + fileInfo.getTmxFileName());
	if (!in.good())
	{
		throw FileLoadException("Unable to load the Tiled tmx file: " + Constants::MapPath + fileInfo.getTmxFileName());
	}

	XML::InputSource src(in);
	
	XML::DOMParser parser;
	AutoPtr<XML::Document> doc = parser.parse(&src);

	MapProperties properties;
	std::map<uint, terrainFactory> terrainFactories;

	GameMap::NavGraphList navGraph;

	XML::NodeIterator iterator(doc, XML::NodeFilter::SHOW_ELEMENT);
	XML::Node* node = iterator.nextNode();
	while (node)
	{
		if (node->nodeName() == "map")
		{
			if (!node->hasAttributes()) throw FileFormatException("The Tiled map file is formatted incorrectly: there are no map attributes.");

			// Load the properties.
			properties = processMapProperties(node);
		
			ScopedNodeList childNodes = node->childNodes();
			for (int i = 0; i < childNodes->length(); ++i)
			{
				auto childNode = childNodes->item(i);
				if (childNode->nodeName() == "tileset")
				{
					terrainFactories = setFactories(childNode);
				}
				else if (childNode->nodeName() == "layer")
				{
					processTerrain(navGraph, terrainFactories, childNode, properties);
				}
			}
		}
		else
		{
			// Postconditions:
			Assert<FileFormatException>(properties.rows != 0, "Properties not loaded from Tiled map file.");
			Assert<FileFormatException>(!navGraph.empty(), "NavGraph not loaded from Tiled map file.");

			// Everything has been processed, so no need to continue iteration.
			break;
		}

		node = iterator.nextNode();
	}

	GameMap::UniquePtr gameMap = make_unique<GameMap>(properties.rows, properties.columns, 
			properties.tileHeight, properties.tileWidth, move(navGraph));
	return move(gameMap);
}