#include "lib_zipfile.h"

ZipFileLib *lib_zipfile = NULL;

static ZipFileLib *CheckLib(LONG offset)
{
	return (ZipFileLib*)CheckLib(LIBRARY_ZIPFILE, offset, (C4DLibrary**)&lib_zipfile);
}

#define ZipLibCall(b) 		ZipFileLib *lib = CheckLib(LIBOFFSET(ZipFileLib, b)); \
															if (!lib || !lib->b) return; \
															(((iZipFile*)this)->*lib->b)

#define ZipLibCallR(a,b) ZipFileLib *lib = CheckLib(LIBOFFSET(ZipFileLib, b)); \
															if (!lib || !lib->b) return a; \
															return (((iZipFile*)this)->*lib->b)

static ZipFileLib *CheckLibZipFile(LONG offset)
{
	return (ZipFileLib*)CheckLib(LIBRARY_ZIPFILE, offset, (C4DLibrary**)&lib_zipfile);
}

ZipFile* ZipFile::Alloc()
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, ZipFile_Alloc)); if (!lib) return NULL;
	return lib->ZipFile_Alloc();	
}

void ZipFile::Free(ZipFile *&p)
{
	if (!p) return;
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, ZipFile_Free)); if (!lib) return;
	lib->ZipFile_Free(p);
	p = NULL;
}

Bool ZipFile::CreateLocalFileName(const Filename &fn, String& str)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, ZipFile_CreateLocalFileName)); if (!lib) return FALSE;
	return lib->ZipFile_CreateLocalFileName(fn, str);	
}

Bool ZipFile::CreateFilename(const String& str, Filename &fn)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, ZipFile_CreateFilename)); if (!lib) return FALSE;
	return lib->ZipFile_CreateFilename(str, fn);	
}

Bool ZipFile::GetFileCRC(const Filename &fn, ULONG &ulCRC)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, ZipFile_GetFileCRC)); if (!lib) return FALSE;
	return lib->ZipFile_GetFileCRC(fn, ulCRC);	
}

ULONG ZipFile::CalcCRC32(const void* pBuffer, LONG lBufferLen, ULONG ulOldCRC)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, ZipFile_CalcCRC32)); if (!lib) return 0;
	return lib->ZipFile_CalcCRC32(pBuffer, lBufferLen, ulOldCRC);	
}

Bool ZipFile::Open(const Filename &fn, const Bool bRead, const LONG lAppend)
{
  ZipLibCallR(FALSE, Open)(fn, bRead, lAppend);
}

Bool ZipFile::OpenEncrypted(const Filename &fn, const Bool bRead, const char* pchKey, LONG lKeyLength, LONG lBlockLength, ULONG lAESFlags, const LONG lAppend)
{
	ZipLibCallR(FALSE, OpenEncrypted)(fn, bRead, pchKey, lKeyLength, lBlockLength, lAESFlags, lAppend);
}

Bool ZipFile::SetSpanning(ULONG ulSpan, Bool bOverwrite)
{
	ZipLibCallR(FALSE, SetSpanning)(ulSpan, bOverwrite);
}

Bool ZipFile::ExtractToDirectory(const Filename& fnZip, const Filename& fnDir, LONG lFlags, ExtractDirectoryCallback fn, void* pData, const char* pChPassword)
{
	ZipLibCallR(FALSE, ExtractToDirectory)(fnZip, fnDir, lFlags, fn, pData, pChPassword);
}

Bool ZipFile::ExtractToDirectoryEx(const Filename& fnZip, const Filename& fnDir, LONG lFlags, ExtractDirectoryCallbackEx fn, void* pData, const char* pChPassword)
{
	ZipLibCallR(FALSE, ExtractToDirectoryEx)(fnZip, fnDir, lFlags, fn, pData, pChPassword);
}

Bool ZipFile::Close()
{
  ZipLibCallR(FALSE, CloseNC)();
}

Bool ZipFile::Close(const char* pchGlobalComment)
{
  ZipLibCallR(FALSE, CloseCC)(pchGlobalComment);
}

Bool ZipFile::Close(const String& strGlobalComment)
{
  ZipLibCallR(FALSE, CloseSC)(strGlobalComment);
}

Bool ZipFile::GetGlobalInfo(ZipFileGlobalInfo &i)
{
  ZipLibCallR(FALSE, GetGlobalInfo)(i);
}

Bool ZipFile::GetGlobalComment(String& str)
{
  ZipLibCallR(FALSE, GetGlobalComment)(str);
}



Bool ZipFile::CreateFileInZip(const String& strName, ZipWriteInfo* pInfo, void* pExtraFieldLocal, ULONG lExtraSizeLocal, void* pExtraFieldGlobal, ULONG lExtraSizeGlobal,
                       String* pstrComment, ZipMethod method, INT lLevel, const char* pchPassword, ULONG ulCryptingCRC)
{
  ZipLibCallR(FALSE, CreateFileInZip)(strName, pInfo, pExtraFieldLocal, lExtraSizeLocal, pExtraFieldGlobal, lExtraSizeGlobal, 
    pstrComment, method, lLevel, pchPassword, ulCryptingCRC);
}

Bool ZipFile::WriteInFileInZip(const void* pBuffer, const ULONG lLen, const LONG lExpectedSize)
{
  ZipLibCallR(FALSE, WriteInFileInZip)(pBuffer, lLen, lExpectedSize);
}

Bool ZipFile::CopyInFileInZip(const Filename& fn, const String& str, const char* pchPassword)
{
  ZipLibCallR(FALSE, CopyInFileInZipA)(fn, str, pchPassword);
}

Bool ZipFile::CopyInFileInZip(const Filename& fn, const String& str, ULONG ulInternalAttributes, ULONG ulExternalAttributes, const char* pchPassword)
{
  ZipLibCallR(FALSE, CopyInFileInZipB)(fn, str, ulInternalAttributes, ulExternalAttributes, pchPassword);
}

Bool ZipFile::SetCompressionLevel(LONG level)
{
	ZipLibCallR(FALSE, SetCompressionLevel)(level);
}

LONG ZipFile::GetCompressionLevel() const
{
	ZipLibCallR(0, GetCompressionLevel)();
}

Bool ZipFile::CloseFileInZip()
{
  ZipLibCallR(FALSE, CloseFileInZip)();
}
Bool ZipFile::CreateDirectoryInZip(const String& strName, ZipFileTime* pTime)
{
  ZipLibCallR(FALSE, CreateDirectoryInZip)(strName, pTime);
}


Bool ZipFile::GoToFirstFile()
{
  ZipLibCallR(FALSE, GoToFirstFile)();
}

Bool ZipFile::GoToNextFile()
{
  ZipLibCallR(FALSE, GoToNextFile)();
}

Bool ZipFile::LocateFile(const String& strName)
{
  ZipLibCallR(FALSE, LocateFile)(strName);
}

Bool ZipFile::GetCurrentFileInfo(ZipFileInfo &i)
{
  ZipLibCallR(FALSE, GetCurrentFileInfoA)(i);
}

Bool ZipFile::GetCurrentFileInfo(String* pstrName, String* pstrComment, void* pExtraField, ULONG lExtraFieldSize)
{
  ZipLibCallR(FALSE, GetCurrentFileInfoB)(pstrName, pstrComment, pExtraField, lExtraFieldSize);
}

Bool ZipFile::OpenCurrentFile(const char* pChPassword)
{
  ZipLibCallR(FALSE, OpenCurrentFile)(pChPassword);
}

Bool ZipFile::CloseCurrentFile()
{
  ZipLibCallR(FALSE, CloseCurrentFile)();
}

LONG ZipFile::ReadCurrentFile(void* pBuffer, ULONG lBufferSize)
{
  ZipLibCallR(-1, ReadCurrentFile)(pBuffer, lBufferSize);
}

LONG ZipFile::GetCurrentFileReadPosition()
{
  ZipLibCallR(FALSE, GetCurrentFileReadPosition)();
}

Bool ZipFile::EndOfCurrentFile()
{
  ZipLibCallR(FALSE, EndOfCurrentFile)();
}

Bool ZipFile::ExtractCurrentFile(const Filename& fnDir, LONG lFlags, const char* pchPassword, Filename* pfnDest)
{
	ZipLibCallR(FALSE, ExtractCurrentFile)(fnDir, lFlags, pchPassword, pfnDest);
}

Bool ZipFile::ExtractCurrentFile(const Filename& fnDir, BaseThread* pThread, LONG lFlags, const char* pchPassword, Filename* pfnDest)
{
	ZipLibCallR(FALSE, ExtractCurrentFileT)(fnDir, pThread, lFlags, pchPassword, pfnDest);
}


Bool GetFileTime(const Filename &fn, UINT &nYear, UINT &nMonth, UINT &nDay, UINT &nHour, UINT &nMinute, UINT &nSec, LONG lType, Bool bIsDir)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, GetFileTime)); if (!lib) return FALSE;
	return lib->GetFileTime(fn, nYear, nMonth, nDay, nHour, nMinute, nSec, lType, bIsDir);	
}

Bool SetFileTime(const Filename &fn, UINT nYear, UINT nMonth, UINT nDay, UINT nHour, UINT nMinute, UINT nSec, LONG lType, Bool bIsDir)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, SetFileTime)); if (!lib) return FALSE;
	return lib->SetFileTime(fn, nYear, nMonth, nDay, nHour, nMinute, nSec, lType, bIsDir);	
}

Bool CompressDataRaw(const void* pSrcData, VLONG lSrcLen, void* pDestData, VLONG* plDestLen, LONG lLevel)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, CompressDataRaw)); if (!lib) return FALSE;
	return lib->CompressDataRaw(pSrcData, lSrcLen, pDestData, plDestLen, lLevel);	
}

Bool UncompressDataRaw(const void* pSrcData, VLONG lSrcLen, void* pDestData, VLONG* plDestLen, VLONG* plRead)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, UncompressDataRaw)); if (!lib) return FALSE;
	return lib->UncompressDataRaw(pSrcData, lSrcLen, pDestData, plDestLen, plRead);	
}

Bool CompressData(const void* pSrcData, VLONG lSrcLen, void *&pDestData, VLONG &lDestLen, LONG lLevel)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, CompressData2)); if (!lib) return FALSE;
	return lib->CompressData2(pSrcData, lSrcLen, pDestData, lDestLen, lLevel);	
}

ZHandle* CompressDataInit(LONG lLevel)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, CompressDataInit)); if (!lib) return NULL;
	return lib->CompressDataInit(lLevel);	
}

Bool CompressDataDoIt(ZHandle *handle, const void* pSrcData, VLONG lSrcLen, void *&pDestData, VLONG &lDestLen, LONG flags)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, CompressDataDoIt)); if (!lib) return FALSE;
	return lib->CompressDataDoIt(handle, pSrcData, lSrcLen, pDestData, lDestLen, flags);	
}

void CompressDataFree(ZHandle *&handle)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, CompressData2)); if (!lib) return;
	lib->CompressDataFree(handle);	
}

Bool UncompressData(const void* pSrcData, VLONG lSrcLen, void *&pDestData, VLONG &lDestLen, VLONG* plRead)
{
	ZipFileLib *lib = CheckLibZipFile(LIBOFFSET(ZipFileLib, UncompressData2)); if (!lib) return FALSE;
	return lib->UncompressData2(pSrcData, lSrcLen, pDestData, lDestLen, plRead);	
}
