//---------------------------------------------------------------------------

#pragma hdrstop

#include "TDllWrap.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

bool TDllWrap::_lastCommandSuccess = true;
bool TDllWrap::_stopOnError = true;
int __stdcall OnConnectionError(char* error)
{
	TLogger *logger = new TLogger();
	logger->Log("ibescript.dll prijavljuje gresku pri konekciji: " + AnsiString(error), llCritical);
	delete logger;
	return 1;
}
int __stdcall OnError(char * text, char * errorMessage)
{
	TLogger *logger = new TLogger();
	logger->Log("ibescript.dll prijavljuje gresku: " + AnsiString(errorMessage), llCritical);
	logger->Log("ibescript.dll tekst: " + AnsiString(text), llCritical);
	TDllWrap::_lastCommandSuccess = false;
	delete logger;
	return 0;
}
int __stdcall OnBefore(char * statement, char * text)
{
	TLogger *logger = new TLogger();
	logger->Log("ibescript.dll radi: " + AnsiString(statement), llCritical);
	if (CompareStr(AnsiString(text), "Executing IBEBlock...") != 0)
	{
		logger->Log(AnsiString(text), llCritical);
	}
	delete logger;
	//if ((!TDllWrap::_lastCommandSuccess)&&TDllWrap::_stopOnError)
	//{
   //		TDllWrap::_logger->Log("Aktivno zaustavljanje zbog greske, staje proces.", llCritical);
   //     return 1;
   //	}
	return 0;
}
int __stdcall OnAfter(char * statement, int success)
{
	if (success != 1)
	{
		TLogger *logger = new TLogger();
		logger->Log("ibescript.dll nije uspeo da izvrsi: " + AnsiString(statement), llCritical);
		delete logger;
		TDllWrap::_lastCommandSuccess = false;
	}
	return 0;
}

TDllWrap::TDllWrap(TFileData &fileData, TFtpData &ftpData,
			TDbData &dbData, bool stopOnError)
{
	_ibeDll = LoadLibraryA(dbData._ibeScriptdll.c_str());
	_connectDB = (TConnectDB)GetProcAddress(_ibeDll, "Connect");
	_disconnectDB = (TDisconnectDB)GetProcAddress(_ibeDll, "Disconnect");
	_executeFile = (TExecute)GetProcAddress(_ibeDll, "ExecScriptFile");
	_executeText = (TExecute)GetProcAddress(_ibeDll, "ExecScriptText");
	_dbData = &dbData;
	_ftpData = &ftpData;
	_fileData = &fileData;
	_stopOnError = stopOnError;
}
void TDllWrap::CleanWorkFolder()
{
	TLogger *logger = new TLogger();
	logger->Log("Brisanje fajlova.", llDebug);
	delete logger;
	if (TDirectory::Exists(_fileData->_tempDirPath))
	{
		TDirectory::Delete(_fileData->_tempDirPath, true);
	}
	ForceDirectories(_fileData->_tempDirPath);
}

bool TDllWrap::ExecuteCommand(Commands command)
{
    _lastCommandSuccess = true;
	AnsiString commandText = "";
	TLogger *logger = new TLogger();
	switch (command)
	{
		case ecOnline:
		case ecOnlineSingle:
		{
			AnsiString single = command == ecOnlineSingle ? "Mode=Single" : "";
			logger->Log("Izvrsavam online baze.", llInfo);
			commandText = "execute ibeblock as begin "
				"err = ibec_OnlineDatabase("
				"'" + _dbData->_fbBaza.ConnectionString() + "',"
				"'ClientLib="
				+ _dbData->_FBdll + ";"
				"User=" + _dbData->_fbBaza._user + "; Password=" + _dbData->_fbBaza._password +";"
				+ single + "'); "
                "if (err is not null) then "
				"exception ERR_EXP err;"
				" end";
			break;
		}
		case ecShutdown:
		case ecShutdownFull:
		{
			AnsiString full = command == ecShutdownFull ? "Mode=Full" : "Mode=Single";
			logger->Log("Izvrsavam shutdown baze.", llInfo);
			commandText = "execute ibeblock as begin "
					"err = ibec_ShutdownDatabase("
					"'" + _dbData->_fbBaza.ConnectionString() + "',"
					"'ClientLib="
					+ _dbData->_FBdll + ";"
					"User=" + _dbData->_fbBaza._user + "; Password=" + _dbData->_fbBaza._password +";"
					+ full + "'); "
					"if (err is not null) then "
					"exception ERR_EXP err;"
					" end";
			break;
		}
		case ecRestore:
			logger->Log("Izvrsavam restore baze.", llInfo);
			commandText = "execute ibeblock as begin "
					"err = ibec_RestoreDatabase("
					"'" + TPath::Combine(_fileData->_targetFolder, _fileData->_archiveName) + "',"
					"'" + _dbData->_fbBaza.BazaPunNaziv() + ".temp" + "',"
					"'ClientLib="
					+ _dbData->_FBdll + ";"
					"User=" + _dbData->_fbBaza._user + "; Password=" + _dbData->_fbBaza._password +";"
					"OneAtATime;INACTIVE;CREATE_DATABASE',null);"
					"if (err is not null) then "
					"exception ERR_EXP err;"
					" end";
			break;
		case ecScript:
			if (ExecuteCommand(ecShutdown) && ExecuteCommand(ecOnlineSingle))
			{
				logger->Log("Konektujem se na bazu.", llInfo);
				ConnectToDb();
		   	}
			break;
		case ecRecompileProcs:
			if (ExecuteCommand(ecShutdown) && ExecuteCommand(ecOnlineSingle))
			{
				ConnectToDb();
				logger->Log("Izvrsavam rekompajliranje svih procedura u bazi.", llInfo);
				commandText = "execute ibeblock as begin "
					"err = ibec_RecompileProcedure(0, '');"
					"if (err <> '') then "
					"exception ERR_EXP err; "
				" end";
			}
			break;
		case ecGetServerLog:
			logger->Log("Uzimam fb serverski log.", llInfo);
			commandText  = "execute ibeblock as begin "
					"ibec_GetServerLog("
					"'ServerName=" + _dbData->_fbBaza.ServerPun() + ";"
					"User=" + _dbData->_fbBaza._user + "; Password=" + _dbData->_fbBaza._password +";"
					"ClientLib=" + _dbData->_FBdll +"','"
					+ TPath::Combine(_fileData->_tempDirPath, "serverLog-" + _helper->TrenutniDatumCist() + ".txt") + "');"
					"if (not ibec_FileExists('"
					+ TPath::Combine(_fileData->_tempDirPath, "serverLog-" + _helper->TrenutniDatumCist() + ".txt") + "')) then "
					"exception ERR_EXP 'Greska prilikom uzimanja serverskog loga.';"
					"end";
			break;

	}
	if (command == ecScript && _lastCommandSuccess)
	{
		logger->Log("Izvrsavam skriptu na bazi.", llInfo);
		_executeFile(_dbData->_scriptFile.c_str(), OnError, OnBefore, OnAfter);
	}else if (_lastCommandSuccess)
	{
		_executeText(commandText.c_str(), OnError, OnBefore, OnAfter);
	}
	if (!_lastCommandSuccess && (command == ecShutdownFull || command == ecShutdown))
	{
		logger->Log("Shutdown nije uspeo, pokusavam Online pa Shutdown.", llCritical);
		if (ExecuteCommand(ecOnlineSingle)&&ExecuteCommand(command))
		{
			logger->Log("Shutdown je sada uspeo", llInfo);
		} else
		{
			logger->Log("Shutdown jos uvek neuspesan, zaustavljam izvrsavanje.", llCritical);
			return false;
        }
	} else if (!_lastCommandSuccess && _stopOnError)
	{
		logger->Log("Proces staje zbog prethodnih gresaka.", llCritical);
		return false;
	}
	if (command == ecRestore)
	{
        _stopOnError = false;
		ExecuteCommand(ecShutdownFull);
		AnsiString fqDbName = _dbData->_fbBaza.BazaPunNaziv();
		DeleteFile(fqDbName);
		RenameFile(fqDbName + ".temp", fqDbName);
	}
	if (command == ecRestore || command == ecScript || command == ecRecompileProcs)
	{
		ExecuteCommand(ecOnline);
	}
	_disconnectDB();
	delete logger;
	return _lastCommandSuccess;
}

void TDllWrap::ConnectToDb()
{
	AnsiString connString = "db_name="
		"'" + _dbData->_fbBaza.ConnectionString() + "';"
		"user_name=SYSDBA; password=masterkey;"
		"clientlib='" + _dbData->_FBdll + "'; sql_role_name=ADMIN; sql_dialect=3;";
	_connectDB(connString.c_str(), OnConnectionError);
}
