#ifndef _DECALCP_H_
#define _DECALCP_H_

template <class T>
class CProxyIACHooksEvents : public IConnectionPointImpl<T, &DIID_IACHooksEvents, CComDynamicUnkArray>
{
public:
	HRESULT Fire_ObjectDestroyed(LONG guid)
	{
		CComVariant varResult;
		T* pT = static_cast<T*>(this);
		int nConnectionIndex;
		CComVariant* pvars = new CComVariant[1];
		int nConnections = m_vec.GetSize();
		
		for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
		{
			pT->Lock();
			CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
			pT->Unlock();
			IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
			if (pDispatch != NULL)
			{
				VariantClear(&varResult);
				pvars[0] = guid;
				DISPPARAMS disp = { pvars, NULL, 1, 0 };
				pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
			}
		}
		delete[] pvars;
		return varResult.scode;
	}

	VARIANT_BOOL Fire_OnChatBoxMessage(BSTR bstrText, LONG lColor)
	{
		VARIANT_BOOL bEatProc = VARIANT_FALSE;
		VARIANT_BOOL bEatLocal = VARIANT_FALSE;
		HRESULT hr = S_OK;
		T * pThis = static_cast<T *>(this);
		int cConnections = m_vec.GetSize();

		for (int iConnection = 0; iConnection < cConnections; iConnection++)
		{
			pThis->Lock();
			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
			pThis->Unlock();

			IDispatch * pConnection = reinterpret_cast<IDispatch *>(punkConnection.p);

			if (pConnection)
			{
				// operator= doesn't accept VARIANT_BOOL *
				VARIANT vt;
				::VariantInit(&vt);
				vt.vt = VT_BYREF | VT_BOOL;
				vt.pboolVal = &bEatLocal;

				CComVariant avarParams[3];
				avarParams[2] = bstrText;
				avarParams[1] = lColor;
				avarParams[0] = vt;
				CComVariant varResult;

				DISPPARAMS params = { avarParams, NULL, 3, 0 };
				hr = pConnection->Invoke(2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);

				if( bEatLocal == VARIANT_TRUE )
					bEatProc = VARIANT_TRUE;
			}
		}

		return bEatProc;
	}

	VARIANT_BOOL Fire_OnCommandLineText( BSTR bstrText )
	{
		VARIANT_BOOL bEatProc = VARIANT_FALSE;
		VARIANT_BOOL bEatLocal = VARIANT_FALSE;
		HRESULT hr = S_OK;
		T * pThis = static_cast<T *>(this);
		int cConnections = m_vec.GetSize();

		for (int iConnection = 0; iConnection < cConnections; iConnection++)
		{
			pThis->Lock();
			CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
			pThis->Unlock();

			IDispatch * pConnection = reinterpret_cast<IDispatch *>(punkConnection.p);

			if (pConnection)
			{
				// operator= doesn't accept VARIANT_BOOL *
				VARIANT vt;
				::VariantInit(&vt);
				vt.vt = VT_BYREF | VT_BOOL;
				vt.pboolVal = &bEatLocal;

				CComVariant avarParams[2];
				avarParams[1] = bstrText;
				avarParams[0] = vt;
				CComVariant varResult;

				DISPPARAMS params = { avarParams, NULL, 2, 0 };
				hr = pConnection->Invoke(3, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);

				if( bEatLocal == VARIANT_TRUE )
					bEatProc = VARIANT_TRUE;
			}
		}

		return bEatProc;
	}

	HRESULT Fire_OnSelectItem(LONG guid)
	{

		CComVariant varResult;
		T* pT = static_cast<T*>(this);
		int nConnectionIndex;
		CComVariant* pvars = new CComVariant[1];
		int nConnections = m_vec.GetSize();

		for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
		{
			pT->Lock();
			CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
			pT->Unlock();
			IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
			if (pDispatch != NULL)
			{
				VariantClear(&varResult);
				pvars[0] = guid;
				DISPPARAMS disp = { pvars, NULL, 1, 0 };
				pDispatch->Invoke(0x4, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
			}
		}
		delete[] pvars;
		return varResult.scode;
	}

  void Fire_OnToolText(BSTR bstrText, VARIANT_BOOL bError)
  {
		T* pT = static_cast<T*>(this);
		int nConnectionIndex;
		CComVariant* pvars = new CComVariant[2];
		int nConnections = m_vec.GetSize();

		for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
		{
			pT->Lock();
			CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
			pT->Unlock();
			IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
			if (pDispatch != NULL)
			{
				// operator= doesn't accept VARIANT_BOOL *
				VARIANT vt;
				::VariantInit(&vt);
				vt.vt = VT_BYREF | VT_BOOL;
				vt.pboolVal = &bError;

				pvars[1] = bstrText;
				pvars[0] = vt;
				DISPPARAMS disp = { pvars, NULL, 2, 0 };
				pDispatch->Invoke(5, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
			}
		}
		delete[] pvars;
  }

  void Fire_OnToolTextAppend(BSTR bstrText, VARIANT_BOOL bError)
  {
		T* pT = static_cast<T*>(this);
		int nConnectionIndex;
		CComVariant* pvars = new CComVariant[2];
		int nConnections = m_vec.GetSize();

		for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
		{
			pT->Lock();
			CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
			pT->Unlock();
			IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
			if (pDispatch != NULL)
			{
				// operator= doesn't accept VARIANT_BOOL *
				VARIANT vt;
				::VariantInit(&vt);
				vt.vt = VT_BYREF | VT_BOOL;
				vt.pboolVal = &bError;

				pvars[1] = bstrText;
				pvars[0] = vt;
				DISPPARAMS disp = { pvars, NULL, 2, 0 };
				pDispatch->Invoke(6, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
			}
		}
		delete[] pvars;
  }
};
#endif