#pragma once

_ATL_FUNC_INFO _infoOnData2 = { CC_STDCALL, VT_I4, 3,{ VT_I4, VT_VARIANT, VT_BSTR } };
_ATL_FUNC_INFO _infoOnDataComplete2 = { CC_STDCALL, VT_I4, 2,{ VT_I4, VT_BSTR } };
_ATL_FUNC_INFO _infoOnClear2 = { CC_STDCALL, VT_I4, 1,{ VT_BSTR } };
_ATL_FUNC_INFO _infoOnClose2 = { CC_STDCALL, VT_I4, 1,{ VT_BSTR } };
_ATL_FUNC_INFO _infoOnInsert2 = { CC_STDCALL, VT_I4, 2,{ VT_VARIANT, VT_BSTR } };
_ATL_FUNC_INFO _infoOnModify2 = { CC_STDCALL, VT_I4, 2,{ VT_VARIANT, VT_BSTR } };
_ATL_FUNC_INFO _infoOnDelete2 = { CC_STDCALL, VT_I4, 2,{ VT_I4, VT_BSTR } };
/*
_ITableEventsFast dispinterface - интерфейс, аналог _ITableEvents с передачей данных массивом SAFEARRAY.
Предполагается использовать при работе с большим потоком данных. Менее удобен, но работа с ним в разы быстрее
работы с аналогом ввиду отсутствия необходимости приводить типы из IDispatch.
*/
IID DIID__ITableEventsFast = __uuidof(_ITableEventsFast);

class CTableEventsFast : public IDispEventSimpleImpl<1, CTableEventsFast, &DIID__ITableEventsFast>
{
public:
	time_t	time1;
	time_t	time2;
	time_t	time3;
	CTableEventsFast()
	{}

	BEGIN_SINK_MAP(CTableEventsFast)
		SINK_ENTRY_INFO(1, DIID__ITableEventsFast, 1, OnData, &_infoOnData2)
		SINK_ENTRY_INFO(1, DIID__ITableEventsFast, 2, OnDataComplete, &_infoOnDataComplete2)
		SINK_ENTRY_INFO(1, DIID__ITableEventsFast, 3, OnClear, &_infoOnClear2)
		SINK_ENTRY_INFO(1, DIID__ITableEventsFast, 4, OnClose, &_infoOnClose2)
		SINK_ENTRY_INFO(1, DIID__ITableEventsFast, 5, OnInsert, &_infoOnInsert2)
		SINK_ENTRY_INFO(1, DIID__ITableEventsFast, 6, OnModify, &_infoOnModify2)
		SINK_ENTRY_INFO(1, DIID__ITableEventsFast, 7, OnDelete, &_infoOnDelete2)
	END_SINK_MAP()


	HRESULT  __stdcall OnData(long Code, VARIANT RowSetArray, BSTR TableName)
	{
		/*static bool once = true;
		if(once)
		{
		time(&time2);
		printf("INTERVAL1 = %d\r\n", time2-time1);
		once = false;
		}*/

		static int i = 0;
		printf("Data block %d\n", ++i);
		Sleep(1000);
		return S_OK;

		long iLBound, iUBound;
		HRESULT hr;

		hr = SafeArrayGetLBound(RowSetArray.parray, 1, &iLBound);
		if (FAILED(hr))
			return hr;
		hr = SafeArrayGetUBound(RowSetArray.parray, 1, &iUBound);
		if (FAILED(hr))
			return hr;
		long lRowSetSize = iUBound - iLBound + 1;

		hr = SafeArrayGetLBound(RowSetArray.parray, 2, &iLBound);
		if (FAILED(hr))
			return hr;
		hr = SafeArrayGetUBound(RowSetArray.parray, 2, &iUBound);
		if (FAILED(hr))
			return hr;
		long lRowSize = iUBound - iLBound + 1;

		std::string String;	String.reserve(10000);
		std::string s9(1, 9), s10(1, 10);

		_bstr_t bstrItem;
		LONG* rgIndexes = new LONG[2];

		for (long i = 0; i < lRowSetSize; ++i)
		{
			rgIndexes[0] = i;
			for (long j = 0; j < lRowSize; ++j)
			{
				rgIndexes[1] = j;
				SafeArrayGetElement(RowSetArray.parray, rgIndexes, bstrItem.GetAddress());
				String.append((const char *)bstrItem);
				String.append(s9);
			}
			String.append(s10);
		}

		delete[] rgIndexes;

		printf("%s\r\n", String.c_str());
		return S_OK;
	}

	HRESULT  __stdcall OnDataComplete(long Result, BSTR TableName)
	{
		time(&time3);
		printf("INTERVAL2 = %d\r\n", time3 - time2);

		printf("\tOnDataComplete()[%d]\n", GetCurrentThreadId());
		return S_OK;
	}

	HRESULT  __stdcall OnClear(BSTR TableName)
	{
		printf("\tOnClear()[%d]\n", GetCurrentThreadId());
		return S_OK;
	}

	HRESULT  __stdcall OnClose(BSTR TableName)
	{
		printf("\tOnClose()[%d]\n", GetCurrentThreadId());
		return S_OK;
	}

	HRESULT  __stdcall OnInsert(VARIANT RowArray, BSTR TableName)
	{
		Sleep(1000);
		static unsigned long ins = 0;
		printf("\tOnInsert()[%d]\t\t%d\n", GetCurrentThreadId(), ins++);

		return S_OK;

		std::string String;	String.reserve(10000);
		std::string s9(1, 9), s10(1, 10);

		bstr_t bstrItem;

		long lColCount = (long)RowArray.parray->rgsabound[0].cElements;
		for (long j = 0; j < lColCount; ++j)
		{
			SafeArrayGetElement(RowArray.parray, &j, bstrItem.GetAddress());
			String.append((const char *)bstrItem);
			String.append(s9);
		}

		String.append(s10);

		printf("%s\r\n", String.c_str());

		return S_OK;
	}

	HRESULT  __stdcall OnModify(VARIANT RowArray, BSTR TableName)
	{
		printf("\tOnModify()[%d]\n", GetCurrentThreadId());
		return S_OK;
	}

	HRESULT  __stdcall OnDelete(long RecId, BSTR TableName)
	{
		printf("\tOnDelete()[%d]\n", GetCurrentThreadId());
		return S_OK;
	}
};
