// Мирошниченко Кирилл aka spock
// #163860836
// e-mail: spock@km.ru
//
#include "stdafx.h"
#include "sp_oledb.h"
#include "sp_cooledb.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//_____________________________________________________________________________
//
enum
{
	funcConnect, 
	funcAttachIB, 
	procClose, 
	funcCreateCommand, 
	lastMethod
};

extern CDataBase7* pDataBase7;
extern CMetaDataCont* pMetaDataCont;
extern CBkEndUI* pBkEndUI;

class CObjID COLEDBData::ObjID;
class CParamDefs COLEDBData::defFnNames;

IMPLEMENT_DYNCREATE(COLEDBData, CBLContext);

//_____________________________________________________________________________
//
COLEDBData::COLEDBData() : CBLContext()
{
	m_bConnected = false;
	m_pInit		 = NULL;

//trad
    m_pMetaDataCont = pMetaDataCont;
//

	if (defFnNames.Empty())
	{
		defFnNames.SetPoolSize(lastMethod, 0);
		defFnNames.AddParam("Connect", "Соединение", funcConnect, 1, 1);
		defFnNames.AddParam("AttachIB", "ПрисоединитьИБ", funcAttachIB, 1, 2);
		defFnNames.AddParam("Close", "Закрыть", procClose, 0, 0);
		defFnNames.AddParam("CreateCommand", "СоздатьКоманду", funcCreateCommand, 1, 0); // OUT:[class COLEDBCommand]
		
	}
}

//_____________________________________________________________________________
//
COLEDBData::~COLEDBData()
{
	m_bConnected = false;
//trad
    CMetaDataWork::UnloadMD(m_pMetaDataCont);
//
}

//_____________________________________________________________________________
//
int COLEDBData::CallAsFunc(int iMethNum, class CValue& rValue, class CValue** ppValue)
{
	USES_CONVERSION;
	
	long ret = 0L;
	HRESULT hr;
	CString strErr;
	
	switch (iMethNum)
	{
		case funcCreateCommand:
			{
				if (!m_bConnected)
				{
					strErr = "Попытка создать команду без подключения к источнику данных!";
					CBLModule::RaiseExtRuntimeError(strErr, 0);

					rValue = 0L;
					return 0;
				}
				
				/*CComPtr<ICommandText> pICommandText;
				hr = m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommandText, (IUnknown**)&pICommandText);
				if (FAILED(hr))
				{
					strErr = "FAILED! IDBCreateCommand::CreateCommand()";
					GetErrorDescription(strErr);
					CBLModule::RaiseExtRuntimeError(strErr, 0);
					
					rValue = 0L;
					return 0;
				}

				COLEDBCommand* pCoOLEDB = new COLEDBCommand(pICommandText);
				*/

				try
				{
					COLEDBCommand* pCoOLEDB = new COLEDBCommand(m_pIDBCreateCommand);
//trad
					pCoOLEDB->m_pOLEDBData = this;
					pCoOLEDB->SetIBProp(m_pMetaDataCont, &m_OLEDBIBSet);
//
					rValue.AssignContext(pCoOLEDB);
					pCoOLEDB->DecrRef();
				}
				catch(...)
				{
					strErr = "FAILED! COLEDBCommand::COLEDBCommand(): Не удалось создать команду!";
					CBLModule::RaiseExtRuntimeError(strErr, 0);
					return 0;
				}

				return 1;
			}
			break;
		
		case funcConnect:
			{
				CComPtr<IDataInitialize> pIDataInit;

				hr = CoCreateInstance(CLSID_MSDAINITIALIZE, NULL, CLSCTX_INPROC_SERVER, IID_IDataInitialize, (void**)&pIDataInit);
				if (FAILED(hr))
				{
					strErr = "FAILED! CoCreateInstance()";
					GetErrorDescription(strErr);
					CBLModule::RaiseExtRuntimeError(strErr, 0);

					rValue = 0L;
					return 0;
				}

				CString strConn(ppValue[0]->GetString());

				hr = pIDataInit->GetDataSource(NULL, CLSCTX_INPROC_SERVER, T2OLE(strConn), IID_IDBInitialize, (IUnknown**)&m_pInit);
				if (FAILED(hr))
				{
					strErr = "FAILED! IDataInitialize::GetDataSource()";
					GetErrorDescription(strErr);
					CBLModule::RaiseExtRuntimeError(strErr, 0);

					rValue = 0L;
					return 0;
				}

				hr = m_pInit->Initialize();
				if (FAILED(hr))
				{
					strErr = "FAILED! IDBInitialize::Initialize()";
					GetErrorDescription(strErr);
					CBLModule::RaiseExtRuntimeError(strErr, 0);

					rValue = 0L;
					return 0;
				}

				CComPtr<IDBCreateSession> pIDBCreateSession;

				hr = m_pInit->QueryInterface(IID_IDBCreateSession, (void**)&pIDBCreateSession);
				if (FAILED(hr))
				{
					strErr = "FAILED! IDBCreateSession::QueryInterface()";
					GetErrorDescription(strErr);
					CBLModule::RaiseExtRuntimeError(strErr, 0);
					
					rValue = 0L;
					return 0;
				}

				hr = pIDBCreateSession->CreateSession(NULL, IID_IDBCreateCommand, (IUnknown**)&m_pIDBCreateCommand);
				if (FAILED(hr))
				{
					strErr = "FAILED! IDBCreateSession::CreateSession()";
					GetErrorDescription(strErr);
					CBLModule::RaiseExtRuntimeError(strErr, 0);
					
					rValue = 0L;
					return 0;
				}

				m_bConnected = true;
				rValue		 = 1L;
				ret			 = 1;
			}
			break;
//trad
		case funcAttachIB:
			{
				if (ppValue[0]->GetTypeCode() != STRING_TYPE_1C ||
					ppValue[1]->GetTypeCode() != STRING_TYPE_1C)
				{
					RuntimeErrorRes(4712); //Неверный тип параметра
				}
				
				CString strFileName(ppValue[0]->GetString());
				strFileName.Format("%s%s", strFileName, "1cv7.md");

				if (!CMetaDataWork::LoadMD(strFileName, m_pMetaDataCont))
					RuntimeErrorRes(28771); //Ошибка загрузки метаданных.
				
				if (ppValue[1]->GetString().IsEmpty())
					*ppValue[1] = "Provider=VFPOLEDB.1;Deleted=Yes;Mode=ReadWrite;Collating Sequence=RUSSIAN;Data Source=" + ppValue[0]->GetString();

				ret = CallAsFunc(funcConnect, rValue, &ppValue[1]);
			}
			break;
//
		default:
			{
				strErr.Format("Нет обработчика метода под номером: %d)", iMethNum);
				CBLModule::RaiseExtRuntimeError(strErr, 0);
			}
	};

	return ret;
}

//_____________________________________________________________________________
//
int COLEDBData::CallAsProc(int iMethNum, class CValue** ppValue)
{
	int ret = 0;
	CString strErr;
	
	switch(iMethNum)
	{
		case procClose:
			{
				m_bConnected = false;
				m_pIDBCreateCommand.Release();
				m_pInit.Release();
				ret = 1;
			}
			break;
		
		default:
			{
				strErr.Format("Нет обработчика метода под номером: %d)", iMethNum);
				CBLModule::RaiseExtRuntimeError(strErr, 0);
			}
	};
	
	return ret;
}

//_____________________________________________________________________________
//
int COLEDBData::GetParamDefValue(int iMethodNum, int iParamNum, class CValue* pDefValue) const
{
	int ret = 0;

	switch (iMethodNum)
	{
		case funcConnect:
			{
				*pDefValue	 = "";
				ret			 = 1;
			}
			break;
//trad

		case funcAttachIB:
			{
				*pDefValue	 = "";
				ret			 = 1;
			}
			break;
//
	};
	
	return ret;
}

//_____________________________________________________________________________
//
int COLEDBData::FindMethod(char const * lpMethodName) const
{
	return defFnNames.GetIndexByName(lpMethodName);
}

//_____________________________________________________________________________
//
char const * COLEDBData::GetMethodName(int iMethodNum, int iMethodAlias) const
{
	return defFnNames[iMethodNum].Names[iMethodAlias];
}

//_____________________________________________________________________________
//
int COLEDBData::GetNMethods(void) const
{
	return defFnNames.Size();
}

//_____________________________________________________________________________
//
int COLEDBData::HasRetVal(int iMethodNum) const
{
	return defFnNames[iMethodNum].HasReturnValue;
}

//_____________________________________________________________________________
//
int COLEDBData::GetNParams(int iMethodNum) const
{
	return defFnNames[iMethodNum].NumberOfParams;
}

//_____________________________________________________________________________
//
char const * COLEDBData::GetCode(void) const
{
	return 0;
}

//_____________________________________________________________________________
//
int COLEDBData::GetDestroyUnRefd(void) const
{
	return 1;
}

//_____________________________________________________________________________
//
class CObjID COLEDBData::GetID(void) const
{
	return ObjID;
}

//_____________________________________________________________________________
//
long COLEDBData::GetTypeID(void) const
{
	return 100L;
}

//_____________________________________________________________________________
//
char const * COLEDBData::GetTypeString(void) const
{
	return "OLEDBData";
}

//_____________________________________________________________________________
//
class CType COLEDBData::GetValueType(void) const
{
	CType tType(100);

	return tType;
}

//_____________________________________________________________________________
//
int COLEDBData::IsExactValue(void) const
{
	return 0;
}

//_____________________________________________________________________________
//
int COLEDBData::IsOleContext(void) const
{
	return 0;
}

//_____________________________________________________________________________
//
int COLEDBData::IsPropReadable(int iPropNum) const
{
	return 1;
}

//_____________________________________________________________________________
//
int COLEDBData::IsPropWritable(int iPropNum) const
{
	return 1;
}

//_____________________________________________________________________________
//
int COLEDBData::IsSerializable(void)
{
	return 0;
}

//_____________________________________________________________________________
//
int COLEDBData::SaveToString(class CString& csStr)
{
	csStr = "";
	return 1;
}

//_____________________________________________________________________________
//
int COLEDBData::GetNProps(void) const
{
	return 0;
}

//_____________________________________________________________________________
//
char const * COLEDBData::GetPropName(int A, int B) const
{
	return NULL;
}

//_____________________________________________________________________________
//
int COLEDBData::GetPropVal(int iPropNum, class CValue& rValue) const
{
	return -1;
}

//_____________________________________________________________________________
//
int COLEDBData::SetPropVal(int iPropNum, class CValue const & vValue)
{
	return -1;
}

//_____________________________________________________________________________
//
int COLEDBData::FindProp(char const * Name) const
{
	return -1;
}

//_____________________________________________________________________________
//
void COLEDBData::GetErrorDescription(CString& strError) const
{
	HRESULT hr;
	
	IErrorInfo* pIErrorInfo;
	hr = ::GetErrorInfo(0, &pIErrorInfo);
	if (SUCCEEDED(hr))
	{
		BSTR errDescr;
		pIErrorInfo->GetDescription(&errDescr);

		strError += ": ";
		strError += errDescr;
		
		::SysFreeString(errDescr);
	}
	pIErrorInfo->Release();
}

//trad
//_____________________________________________________________________________
//
CDate CIBSetOLEDB::GetDateTimeTA(CEventTime &TimeTA)
{
	return CIBSet::GetDateTimeTA(TimeTA);
}
int CIBSetOLEDB::GetDataSourceType()
{
    return DATA_SOURCE_TYPE_DBF;
}
enum PeriodType CIBSetOLEDB::GetRestsSnapShotPeriod()
{
    return CIBSet::GetRestsSnapShotPeriod();
}
//