void MPQArchive::close()
{
	libmpq_archive_close(&mpq_a);
	for(ArchiveSet::iterator it=gOpenArchives.begin(); it!=gOpenArchives.end();++it)
	{
		mpq_archive &mpq_b = **it;
		if (&mpq_b == &mpq_a) {
			gOpenArchives.erase(it);
			//delete (*it);
			return;
		}
	}

}
MPQArchive::MPQArchive(wxString filename) : ok(false)
{
	wxLogMessage(wxT("Opening %s %s"), filename.Mid(gamePath.Len()).c_str(), isPartialMPQ(filename) ? "(Partial)" : "");
	g_modelViewer->SetStatusText(wxT("Initiating "+filename+wxT(" Archive")));
#ifndef _MINGW
	if (!SFileOpenArchive(filename.fn_str(), 0, MPQ_OPEN_FORCE_MPQ_V1|MPQ_OPEN_READ_ONLY, &mpq_a )) {
#else
	if (!SFileOpenArchive(filename.char_str(), 0, MPQ_OPEN_FORCE_MPQ_V1|MPQ_OPEN_READ_ONLY, &mpq_a )) {
#endif
		int nError = GetLastError();
		wxLogMessage(wxT("Error opening archive %s, error #: 0x%X"), filename.Mid(gamePath.Len()).c_str(), nError);
		return;
	}

	
	// do patch, but skip cache\ directory
	if (!(filename.BeforeLast(SLASH).Lower().Contains(wxT("cache")) && 
		filename.AfterLast(SLASH).Lower().StartsWith(wxT("patch"))) &&
		!isPartialMPQ(filename)) { // skip the PTCH files atrchives
		// do patch
		for(ssize_t j=mpqArchives.GetCount()-1; j>=0; j--) {
			if (!mpqArchives[j].AfterLast(SLASH).StartsWith(wxT("wow-update-")))
				continue;
			if (mpqArchives[j].AfterLast(SLASH).Len() == strlen("wow-update-xxxxx.mpq")) {
#ifndef _MINGW
				SFileOpenPatchArchive(mpq_a, mpqArchives[j].fn_str(), "base", 0);
				SFileOpenPatchArchive(mpq_a, mpqArchives[j].fn_str(), langName.fn_str(), 0);
#else
				SFileOpenPatchArchive(mpq_a, mpqArchives[j].char_str(), "base", 0);
				SFileOpenPatchArchive(mpq_a, mpqArchives[j].char_str(), langName.char_str(), 0);
#endif
				// too many for ptr client, just comment it
				// wxLogMessage(wxT("Appending base & %s patch %s"), langName.c_str(), mpqArchives[j].Mid(gamePath.Len()).c_str());
			} else if (mpqArchives[j].BeforeLast(SLASH) == filename.BeforeLast(SLASH)) { // same directory only
#ifndef _MINGW
				SFileOpenPatchArchive(mpq_a, mpqArchives[j].fn_str(), "", 0);
#else
				SFileOpenPatchArchive(mpq_a, mpqArchives[j].char_str(), "", 0);
#endif
				// wxLogMessage(wxT("Appending patch %s"), mpqArchives[j].Mid(gamePath.Len()).c_str());
			}
		}
	}

	ok = true;
	gOpenArchives.push_back( make_pair( filename, &mpq_a ) );
}

MPQArchive::~MPQArchive()
{
	/*
	for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i)
	{
		mpq_archive &mpq_a = **i;
		
		free(mpq_a.header);
	}
	*/
	//gOpenArchives.erase(gOpenArchives.begin(), gOpenArchives.end());
}

bool MPQArchive::isPartialMPQ(wxString filename)
{
	if (filename.AfterLast(SLASH).StartsWith(wxT("wow-update-")))
		return true;
	return false;
}

void MPQArchive::close()
{
	if (ok == false)
		return;
	SFileCloseArchive(mpq_a);
	for(ArchiveSet::iterator it=gOpenArchives.begin(); it!=gOpenArchives.end();++it)
	{
		HANDLE &mpq_b = *it->second;
		if (&mpq_b == &mpq_a) {
			gOpenArchives.erase(it);
			//delete (*it);
			return;
		}
	}
	
}

bool MPQFile::isPartialMPQ(wxString filename)
{
	if (filename.AfterLast(SLASH).StartsWith(wxT("wow-update-")))
		return true;
	return false;
}

void
MPQFile::openFile(wxString filename)
{
	eof = false;
	buffer = 0;
	pointer = 0;
	size = 0;
	if( useLocalFiles ) {
		wxString fn1 = wxGetCwd()+SLASH+wxT("Import")+SLASH;
		wxString fn2 = fn1;
		wxString fn3 = gamePath;
		fn1.Append(filename);
		fn2.Append(filename.AfterLast(SLASH));
		fn3.Append(filename);

		wxString fns[] = { fn1, fn2, fn3 };
		for(size_t i=0; i<WXSIZEOF(fns); i++) {
			wxString fn = fns[i];
			if (wxFile::Exists(fn)) {
				// success
				wxFile file;
				// if successfully opened
				if (file.Open(fn, wxFile::read)) {
					size = file.Length();
					if (size > 0) {
						buffer = new unsigned char[size];
						// if successfully read data
						if (file.Read(buffer, size) > 0) {
							eof = false;
							file.Close();
							return;
						} else {
							wxDELETEA(buffer);
							eof = true;
							size = 0;
						}
					}
					file.Close();
				}
			}
		}
	}

	// zhCN alternate file mode
	if (bAlternate && !filename.Lower().StartsWith(wxT("alternate"))) {
		wxString alterName = wxT("alternate")+SLASH+filename;

		for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end(); ++i)
		{
			HANDLE &mpq_a = *i->second;

			HANDLE fh;
#ifndef _MINGW
			if( !SFileOpenFileEx( mpq_a, alterName.fn_str(), SFILE_OPEN_PATCHED_FILE, &fh ) )
#else
			if( !SFileOpenFileEx( mpq_a, alterName.char_str(), SFILE_OPEN_PATCHED_FILE, &fh ) )
#endif
				continue;

			// Found!
			DWORD filesize = SFileGetFileSize( fh );
			size = filesize;

			// HACK: in patch.mpq some files don't want to open and give 1 for filesize
			if (size<=1) {
				eof = true;
				buffer = 0;
				return;
			}

			buffer = new unsigned char[size];
			SFileReadFile( fh, buffer, (DWORD)size );
			SFileCloseFile( fh );

			return;
		}
	}

	for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end(); ++i)
	{
		HANDLE &mpq_a = *i->second;

		HANDLE fh;
#ifndef _MINGW
		if( !SFileOpenFileEx( mpq_a, filename.fn_str(), SFILE_OPEN_PATCHED_FILE, &fh ) )
#else
		if( !SFileOpenFileEx( mpq_a, filename.char_str(), SFILE_OPEN_PATCHED_FILE, &fh ) )
#endif
			continue;

		// Found!
		DWORD filesize = SFileGetFileSize( fh );
		size = filesize;

		// HACK: in patch.mpq some files don't want to open and give 1 for filesize
		if (size<=1) {
			eof = true;
			buffer = 0;
			return;
		}

		buffer = new unsigned char[size];
		SFileReadFile( fh, buffer, (DWORD)size );
		SFileCloseFile( fh );

		return;
	}

	eof = true;
	buffer = 0;
}