//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pszFilename - 
//			bIndexOnly - 
// Output : int
//-----------------------------------------------------------------------------
int CPrefabLibraryRMF::Save(LPCTSTR pszFilename, BOOL bIndexOnly)
{
	// temp storage
	static char szFile[MAX_PATH];

	// if only saving index, special code -
	if(bIndexOnly && m_file.is_open())
	{
		// close file, reopen in binary write
		m_file.close();
		if(Prefabs.GetCount())
		{
			// change size of file first
			int iHandle = _open(m_strOpenFileName, _O_BINARY | _O_WRONLY);
			_chsize(iHandle, m_dwDirOffset);
			_close(iHandle);
		}

		fstream file(m_strOpenFileName, ios::binary | ios::out);

		// write string header
		file << pLibHeader;
		// write binary header (in case notes have changed)
		PrefabLibraryHeader plh;
		plh.dwNumEntries = Prefabs.GetCount();
		plh.fVersion = fLibVersion;
		plh.dwDirOffset = m_dwDirOffset;
		strcpy(plh.szNotes, szNotes);
		file.write((char*)&plh, sizeof plh);

		// recreate a directory and write it
		PrefabHeader *ph = new PrefabHeader[Prefabs.GetCount()];
		int iCur = 0;

		POSITION p = Prefabs.GetHeadPosition();
		while(p)
		{
			CPrefab *pPrefab = Prefabs.GetNext(p);

			// setup this dir entry
			ph[iCur].dwOffset = pPrefab->dwFileOffset;
			ph[iCur].dwSize = pPrefab->dwFileSize;
			strcpy(ph[iCur].szName, pPrefab->GetName());
			strcpy(ph[iCur].szNotes, pPrefab->GetNotes());
			ph[iCur].iType = pPrefab->GetType();

			++iCur;	// increase current directory entry
		}

		// write directory
		file.seekp(m_dwDirOffset);
		file.write((char*)ph, sizeof(*ph) * Prefabs.GetCount());
		file.close();

		// re-open
		m_file.open(m_strOpenFileName, ios::in | ios::binary | ios::nocreate);
		return 1;
	}

	if(pszFilename == NULL)
	{
		pszFilename = szFile;

		if(m_strOpenFileName.IsEmpty())
		{
			char szNewFilename[MAX_PATH];
			CWorldcraft *pApp = (CWorldcraft*) AfxGetApp();
			pApp->GetDirectory(DIR_PREFABS, szNewFilename);

			sprintf(szNewFilename + strlen(szNewFilename), "\\%s.ol", m_szName);

			// make a name
			m_strOpenFileName = szNewFilename;
		}

		strcpy(szFile, m_strOpenFileName);
	}
	else
	{
		strcpy(szFile, pszFilename);
		SetNameFromFilename(pszFilename);
	}

	// open temp file to save to.. then delete & rename old one.
	CString strTempFileName = "Temporary Prefab Library.$$$";
	fstream file;
	file.open(strTempFileName, ios::binary | ios::out);

	// write string header
	file << pLibHeader;

	// write binary header
	// save current position so we can seek back and rewrite it
	DWORD dwBinaryHeaderOffset = file.tellp();
	PrefabLibraryHeader plh;
	plh.dwNumEntries = Prefabs.GetCount();
	plh.fVersion = fLibVersion;
	strcpy(plh.szNotes, szNotes);
	file.write((char*)&plh, sizeof plh);

	// allocate memory for directory
	PrefabHeader *ph = new PrefabHeader[plh.dwNumEntries];
	int iCur = 0;

	char *pCopyBuf = new char[64000];

	// write each prefab
	POSITION p = Prefabs.GetHeadPosition();
	while (p)
	{
		CPrefabRMF *pPrefab = (CPrefabRMF *)Prefabs.GetNext(p);

		// setup this dir entry
		ph[iCur].dwOffset = file.tellp();
		strcpy(ph[iCur].szName, pPrefab->GetName());
		strcpy(ph[iCur].szNotes, pPrefab->GetNotes());
		ph[iCur].iType = pPrefab->GetType();

		if(pPrefab->IsLoaded())
		{
			// it's loaded - save in native method
			pPrefab->Save(file, CPrefab::lsUpdateFilePos);
		}
		else
		{
			// it's not loaded - save with quick method by copying
			// bytes directly from the existing file
			ASSERT(m_file.is_open());
			m_file.seekg(pPrefab->dwFileOffset);
			DWORD dwToRead = 64000, dwCopied = 0;
			while(dwToRead == 64000)
			{
				if(dwCopied + dwToRead > pPrefab->dwFileSize)
					dwToRead = pPrefab->dwFileSize - dwCopied;
				m_file.read(pCopyBuf, dwToRead);
				file.write(pCopyBuf, dwToRead);
				dwCopied += dwToRead;
			}
		}

		// set offset info HERE because we might use it above
		pPrefab->dwFileOffset = ph[iCur].dwOffset;

		// set size info
		ph[iCur].dwSize = pPrefab->dwFileSize = 
			file.tellp() - ph[iCur].dwOffset;

		++iCur;	// increase current directory entry
	}

	// delete copy buf
	delete[] pCopyBuf;

	// rewrite binary header
	plh.dwDirOffset = m_dwDirOffset = file.tellp();
	file.seekp(dwBinaryHeaderOffset);
	file.write((char*)&plh, sizeof(plh));
	file.seekp(0, ios::end);

	// write directory
	file.write((char*)ph, sizeof(*ph) * plh.dwNumEntries);
	file.close();	// close temp file
	
	// delete original and rename
	m_file.close();	// might already be open.. might not.
	remove(m_strOpenFileName);

	m_strOpenFileName = szFile;
	int iRvl = rename(strTempFileName, m_strOpenFileName);
	
	// reopen original
	m_file.open(m_strOpenFileName, ios::in | ios::binary | ios::nocreate);

	return 1;
}