/*******************************************************************************
  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 338 2010-09-23 07:32:10Z 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_t _llTypeId)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	if (! this->lib.Load(_szLibName))
	{
		return false;
	}

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

	GetAPIAddress("LoadPlugin", p);
	this->nErrorCode = ((int (__stdcall *)(const wxString &, wxULongLong_t)) p)(_szArcName, _llTypeId);
	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_t _llSubOption, void * _pPtr)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	GetAPIAddress("GetPluginInformation", p);
	this->nErrorCode = ((int (__stdcall *)(unsigned int, wxULongLong_t, 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->fCompressHeader    = false;
	_fiInfo->fEncryptKeyFile    = false;
	_fiInfo->fEncryptPassword   = false;
	_fiInfo->fEncryptHeader     = false;
	_fiInfo->fMMOptimize        = false;
	_fiInfo->fMultiVolume       = false;
	_fiInfo->fSolid             = false;
	_fiInfo->nCompressLevelMin  = 0;
	_fiInfo->nCompressLevelMax  = 0;
	_fiInfo->nRecoveryRecordMin = 0;
	_fiInfo->nRecoveryRecordMax = 0;
	_fiInfo->szTypeName.Empty();
	_fiInfo->szSuffix.Empty();
	_fiInfo->szEngineName.Empty();
	_fiInfo->szTPIName.Empty();
	_fiInfo->eSupportedCommand = 0;
	_fiInfo->nTypeId           = 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::OpenArchive(const wxString & _szArcName, wxULongLong_t * _llFileCount)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	GetAPIAddress("OpenArchive", p);
	this->nErrorCode = ((int (__stdcall *)(const wxString &, void * *, wxULongLong_t *)) p)(_szArcName, & this->archive, _llFileCount);
	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->eDanger        = 0;
	_fiInfo->eOSType        = 0;
	_fiInfo->nPackedSize    = 0;
	_fiInfo->nUnpackedSize  = 0;
	_fiInfo->fnFileName.Clear();
	_fiInfo->szStoredName.Empty();
	_fiInfo->szMethod.Empty();
	_fiInfo->szComment.Empty();
	_fiInfo->wCompressRatio = 0;
	_fiInfo->nFileId        = 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->fSFX           = false;
	_aiInfo->fSolid			= false;
	_aiInfo->fMMOptimize    = false;
	_aiInfo->fEncryptData   = false;
	_aiInfo->fEncryptHeader = false;
	_aiInfo->fCompressHeader= false;
	_aiInfo->nCompressLevel = 0;
	_aiInfo->nRecoveryRecord= 0;
	_aiInfo->tmAccess       = 0;
	_aiInfo->tmCreate       = 0;
	_aiInfo->tmModified     = 0;
	_aiInfo->eOSType        = 0;
	_aiInfo->nFileSize      = 0;
	_aiInfo->nPackedSize    = 0;
	_aiInfo->nReadSize      = 0;
	_aiInfo->nUnpackedSize  = 0;
	_aiInfo->nSplitSize     = 0;
	_aiInfo->fnArchive.Clear();
	_aiInfo->szComment.Empty();
	_aiInfo->wCompressRatio = 0;
	_aiInfo->pCustomInfo    = NULL;
	// FORMATINFO
	_aiInfo->fiInfo.fComment           = false;
	_aiInfo->fiInfo.fCompressHeader    = 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.nCompressLevelMin  = 0;
	_aiInfo->fiInfo.nCompressLevelMax  = 0;
	_aiInfo->fiInfo.nRecoveryRecordMin = 0;
	_aiInfo->fiInfo.nRecoveryRecordMax = 0;
	_aiInfo->fiInfo.szTypeName.Empty();
	_aiInfo->fiInfo.szSuffix.Empty();
	_aiInfo->fiInfo.szEngineName.Empty();
	_aiInfo->fiInfo.szTPIName.Empty();
	_aiInfo->fiInfo.eSupportedCommand = 0;
	_aiInfo->fiInfo.nTypeId           = 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(wxULongLong_t _eCommand, TPI_SWITCHES * _swInfo, const wxString & _szArcName, const wxArrayString & _szFiles)
{
	this->nErrorCode = TPI_ERROR_SUCCESS;
	GetAPIAddress("Command", p);
	this->nErrorCode = ((int (__stdcall *)(wxULongLong_t, TPI_SWITCHES *, const wxString &, const wxArrayString &)) p)(_eCommand, _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;
}
