/*
============
idAASBuild::Build
============
*/
bool idAASBuild::Build( const idStr& fileName, const idAASSettings* settings )
{
	int i, bit, mask, startTime;
	idMapFile* mapFile;
	idBrushList brushList;
	idList<idBrushList*> expandedBrushes;
	idBrush* b;
	idBrushBSP bsp;
	idStr name;
	idAASReach reach;
	idAASCluster cluster;
	idStrList entityClassNames;
	
	startTime = Sys_Milliseconds();
	
	Shutdown();
	
	aasSettings = settings;
	
	name = fileName;
	name.SetFileExtension( "map" );
	
	mapFile = new idMapFile;
	if( !mapFile->Parse( name ) )
	{
		delete mapFile;
		common->Error( "Couldn't load map file: '%s'", name.c_str() );
		return false;
	}
	
	// check if this map has any entities that use this AAS file
	if( !CheckForEntities( mapFile, entityClassNames ) )
	{
		delete mapFile;
		common->Printf( "no entities in map that use %s\n", settings->fileExtension.c_str() );
		return true;
	}
	
	// load map file brushes
	brushList = AddBrushesForMapFile( mapFile, brushList );
	
	// if empty map
	if( brushList.Num() == 0 )
	{
		delete mapFile;
		common->Error( "%s is empty", name.c_str() );
		return false;
	}
	
	// merge as many brushes as possible before expansion
	brushList.Merge( MergeAllowed );
	
	// if there is a .proc file newer than the .map file
	if( LoadProcBSP( fileName, mapFile->GetFileTime() ) )
	{
		ClipBrushSidesWithProcBSP( brushList );
		DeleteProcBSP();
	}
	
	// make copies of the brush list
	expandedBrushes.Append( &brushList );
	for( i = 1; i < aasSettings->numBoundingBoxes; i++ )
	{
		expandedBrushes.Append( brushList.Copy() );
	}
	
	// expand brushes for the axial bounding boxes
	mask = AREACONTENTS_SOLID;
	for( i = 0; i < expandedBrushes.Num(); i++ )
	{
		for( b = expandedBrushes[i]->Head(); b; b = b->Next() )
		{
			b->ExpandForAxialBox( aasSettings->boundingBoxes[i] );
			bit = 1 << ( i + AREACONTENTS_BBOX_BIT );
			mask |= bit;
			b->SetContents( b->GetContents() | bit );
		}
	}
	
	// move all brushes back into the original list
	for( i = 1; i < aasSettings->numBoundingBoxes; i++ )
	{
		brushList.AddToTail( *expandedBrushes[i] );
		delete expandedBrushes[i];
	}
	
	if( aasSettings->writeBrushMap )
	{
		bsp.WriteBrushMap( fileName, "_" + aasSettings->fileExtension, AREACONTENTS_SOLID );
	}
	
	// build BSP tree from brushes
	bsp.Build( brushList, AREACONTENTS_SOLID, ExpandedChopAllowed, ExpandedMergeAllowed );
	
	// only solid nodes with all bits set for all bounding boxes need to stay solid
	ChangeMultipleBoundingBoxContents_r( bsp.GetRootNode(), mask );
	
	// portalize the bsp tree
	bsp.Portalize();
	
	// remove subspaces not reachable by entities
	if( !bsp.RemoveOutside( mapFile, AREACONTENTS_SOLID, entityClassNames ) )
	{
		bsp.LeakFile( name );
		delete mapFile;
		common->Printf( "%s has no outside", name.c_str() );
		return false;
	}
	
	// gravitational subdivision
	GravitationalSubdivision( bsp );
	
	// merge portals where possible
	bsp.MergePortals( AREACONTENTS_SOLID );
	
	// melt portal windings
	bsp.MeltPortals( AREACONTENTS_SOLID );
	
	if( aasSettings->writeBrushMap )
	{
		WriteLedgeMap( fileName, "_" + aasSettings->fileExtension + "_ledge" );
	}
	
	// ledge subdivisions
	LedgeSubdivision( bsp );
	
	// merge leaf nodes
	MergeLeafNodes( bsp );
	
	// merge portals where possible
	bsp.MergePortals( AREACONTENTS_SOLID );
	
	// melt portal windings
	bsp.MeltPortals( AREACONTENTS_SOLID );
	
	// store the file from the bsp tree
	StoreFile( bsp );
	file->settings = *aasSettings;
	
	// calculate reachability
	reach.Build( mapFile, file );
	
	// build clusters
	cluster.Build( file );
	
	// optimize the file
	if( !aasSettings->noOptimize )
	{
		file->Optimize();
	}
	
	// write the file
	name.SetFileExtension( aasSettings->fileExtension );
	file->Write( name, mapFile->GetGeometryCRC() );
	
	// delete the map file
	delete mapFile;
	
	common->Printf( "%6d seconds to create AAS\n", ( Sys_Milliseconds() - startTime ) / 1000 );
	
	return true;
}
void CompoundFileStore::StoreAllFiles()
{
    std::map<std::string,std::tstring>::iterator iter;
    for( iter = m_mUniqueNameToFiles.begin(); iter != m_mUniqueNameToFiles.end(); iter++ )
        StoreFile( iter->first );
}