/*******************************************************************************
  TPI - flexible but useless plug-in framework.
  Copyright (C) 2002-2009 Silky

  This library is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the Free
  Software Foundation; either version 2.1 of the License, or (at your option)
  any later version.

  This library is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
  for more details.

  You should have received a copy of the GNU Lesser General Public License along
  with this library; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

  $Id: TPIHandle.cpp 136 2009-11-21 11:43:29Z sirakaba $
*******************************************************************************/

//******************************************************************************
//    Includes
//******************************************************************************

#define wxUSE_DYNLIB_CLASS 1
#include "../header/plugin.h"
#include <wx/dynlib.h>
#include "TPIHandle.h"

#define GetAPIAddress(name, p) \
	if (! this->lib.HasSymbol(wxT(name))) \
	{ \
		return false; \
	} \
	void * p = this->lib.GetSymbol(wxT(name)); \
	if (! p) \
	{ \
		return false; \
	}

//******************************************************************************
//    Class (TPIHandle)
//******************************************************************************

TPIHandle::TPIHandle(void)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
}

TPIHandle::~TPIHandle(void)
{
	this->FreeLibrary();
}

bool TPIHandle::InitLibrary(const wxString & _szLibName, const wxString & _szArcName, wxULongLong _llSubOption)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	this->lib.Load(_szLibName);
	if (! this->lib.IsLoaded())
	{
		return false;
	}

	if (_szArcName.IsEmpty())
	{
		return true;
	}

	GetAPIAddress("LoadPlugin", p);
	this->nErrorCode = ((int (__stdcall *)(const wxString &, wxULongLong)) p)(_szArcName, _llSubOption);
	return this->nErrorCode == TPI_ERROR_SUCCESS;
}

bool TPIHandle::FreeLibrary(void)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	if (! this->lib.IsLoaded())
	{
		return false;
	}

	GetAPIAddress("FreePlugin", p);
	this->nErrorCode = ((int (__stdcall *)(void *)) p)(NULL);

	this->lib.Unload();
	return this->nErrorCode == TPI_ERROR_SUCCESS;
}

bool TPIHandle::GetPluginInformation(unsigned int _uInfoId, wxULongLong _llSubOption, void * _pPtr)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	GetAPIAddress("GetPluginInformation", p);
	this->nErrorCode = ((int (__stdcall *)(unsigned int, wxULongLong, void *)) p)(_uInfoId, _llSubOption, _pPtr);
	return this->nErrorCode == TPI_ERROR_SUCCESS;
}

bool TPIHandle::GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	if (! _fiInfo)
	{
		return false;
	}

	// Initialization.
	_fiInfo->fArchive           = false;
	_fiInfo->fComment           = false;
	_fiInfo->fEncryptKeyFile    = false;
	_fiInfo->fEncryptPassword   = false;
	_fiInfo->fEncryptHeader     = false;
	_fiInfo->fMMOptimize        = false;
	_fiInfo->fMultiVolume       = false;
	_fiInfo->fSolid             = false;
	_fiInfo->sCompressLevelMin  = 0;
	_fiInfo->sCompressLevelMax  = 0;
	_fiInfo->sRecoveryRecordMin = 0;
	_fiInfo->sRecoveryRecordMax = 0;
	_fiInfo->szTypeName.Clear();
	_fiInfo->szSuffix.Clear();
	_fiInfo->szEngineName.Clear();
	_fiInfo->szTPIName.Clear();
	_fiInfo->llSupportedCommand = 0;
	_fiInfo->llTypeId           = 0;
	_fiInfo->pCustomInfo    = NULL;

	GetAPIAddress("GetFormatInformation", p);
	this->nErrorCode = ((int (__stdcall *)(TPI_FORMATINFO *, bool)) p)(_fiInfo, _bFirst);
	return this->nErrorCode == TPI_ERROR_SUCCESS;
}

bool TPIHandle::CheckArchive(const wxString & _szArcName, int * _nFileCount)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	GetAPIAddress("CheckArchive", p);
	this->nErrorCode = ((int (__stdcall *)(const wxString &, int *)) p)(_szArcName, _nFileCount);
	return this->nErrorCode == TPI_ERROR_SUCCESS;
}

bool TPIHandle::OpenArchive(const wxString & _szArcName)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	GetAPIAddress("OpenArchive", p);
	this->nErrorCode = ((int (__stdcall *)(const wxString &, void * *)) p)(_szArcName, & this->archive);
	return this->nErrorCode == TPI_ERROR_SUCCESS;
}

bool TPIHandle::CloseArchive(void)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	GetAPIAddress("CloseArchive", p);
	this->nErrorCode = ((int (__stdcall *)(void *)) p)(this->archive);
	return this->nErrorCode == TPI_ERROR_SUCCESS;
}

bool TPIHandle::GetFileInformation(TPI_FILEINFO * _fiInfo, bool _bFirst)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	if (! _fiInfo)
	{
		return false;
	}

	// Initialization.
	_fiInfo->dwAttribute    = 0;
	_fiInfo->dwCRC32        = 0;
	_fiInfo->tmAccess       = 0;
	_fiInfo->tmCreate       = 0;
	_fiInfo->tmModified     = 0;
	_fiInfo->uDanger        = 0;
	_fiInfo->uOSType        = 0;
	_fiInfo->llPackedSize   = 0;
	_fiInfo->llUnpackedSize = 0;
	_fiInfo->szStoredName.Clear();
	_fiInfo->szMethod.Clear();
	_fiInfo->szComment.Clear();
	_fiInfo->wCompressRatio = 0;
	_fiInfo->llFileID       = 0;
	_fiInfo->pCustomInfo    = NULL;

	GetAPIAddress("GetFileInformation", p);
	this->nErrorCode = ((int (__stdcall *)(void *, TPI_FILEINFO *, bool)) p)(this->archive, _fiInfo, _bFirst);
	return this->nErrorCode == TPI_ERROR_SUCCESS;
}

bool TPIHandle::GetArchiveInformation(TPI_ARCHIVEINFO * _aiInfo)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	if (! _aiInfo)
	{
		return false;
	}

	// Initialization.
	_aiInfo->fSolid			= false;
	_aiInfo->fMMOptimize    = false;
	_aiInfo->fEncryptData   = false;
	_aiInfo->fEncryptHeader = false;
	_aiInfo->sCompressLevel = 0;
	_aiInfo->sRecoveryRecord= 0;
	_aiInfo->tmAccess       = 0;
	_aiInfo->tmCreate       = 0;
	_aiInfo->tmModified     = 0;
	_aiInfo->nSFXType       = 0;
	_aiInfo->uOSType        = 0;
	_aiInfo->llFileSize     = 0;
	_aiInfo->llPackedSize   = 0;
	_aiInfo->llReadSize     = 0;
	_aiInfo->llUnpackedSize = 0;
	_aiInfo->llSplitSize    = 0;
	_aiInfo->szComment.Clear();
	_aiInfo->wCompressRatio = 0;
	_aiInfo->pCustomInfo    = NULL;
	// FORMATINFO
	_aiInfo->fiInfo.fComment           = false;
	_aiInfo->fiInfo.fEncryptKeyFile    = false;
	_aiInfo->fiInfo.fEncryptPassword   = false;
	_aiInfo->fiInfo.fEncryptHeader     = false;
	_aiInfo->fiInfo.fMMOptimize        = false;
	_aiInfo->fiInfo.fMultiVolume       = false;
	_aiInfo->fiInfo.fSolid             = false;
	_aiInfo->fiInfo.sCompressLevelMin  = 0;
	_aiInfo->fiInfo.sCompressLevelMax  = 0;
	_aiInfo->fiInfo.sRecoveryRecordMin = 0;
	_aiInfo->fiInfo.sRecoveryRecordMax = 0;
	_aiInfo->fiInfo.szTypeName.Clear();
	_aiInfo->fiInfo.szSuffix.Clear();
	_aiInfo->fiInfo.szEngineName.Clear();
	_aiInfo->fiInfo.szTPIName.Clear();
	_aiInfo->fiInfo.llSupportedCommand = 0;
	_aiInfo->fiInfo.llTypeId           = 0;
	_aiInfo->fiInfo.pCustomInfo    = NULL;

	GetAPIAddress("GetArchiveInformation", p);
	this->nErrorCode = ((int (__stdcall *)(void *, TPI_ARCHIVEINFO *)) p)(this->archive, _aiInfo);
	return this->nErrorCode == TPI_ERROR_SUCCESS;
}

bool TPIHandle::Command(unsigned int _uCommand, TPI_SWITCHES * _swInfo, const wxString & _szArcName, const wxArrayString & _szFiles)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	GetAPIAddress("Command", p);
	this->nErrorCode = ((int (__stdcall *)(unsigned int, TPI_SWITCHES *, const wxString &, const wxArrayString &)) p)(_uCommand, _swInfo, _szArcName, _szFiles);
	return this->nErrorCode == TPI_ERROR_SUCCESS;
}

bool TPIHandle::SetCallbackProc(TPI_PROC _prProc)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	GetAPIAddress("SetCallbackProc", p);
	this->nErrorCode = ((int (__stdcall *)(TPI_PROC)) p)(_prProc);
	return this->nErrorCode == TPI_ERROR_SUCCESS;
}
