#include "StdAfx.h"
#include ".\mylistener.h"

#include "../../Strawberry.h"
#include "../../MainFrm.h"

ComSupport::CMyListener::~CMyListener(void)
{
	if(m_pListener == NULL)
		return;

	if(m_spConnectionPoint == NULL)
		return;

	try
	{
		HRESULT hr = m_spConnectionPoint->Unadvise(m_dwCockie);
		ASSERT(SUCCEEDED(hr));
	}
	catch(...)
	{
		ASSERT(FALSE);//Unadvise throws - may be the COM server was closed
	}

	m_pListener->Release();
	m_pListener = NULL;
}


BOOL ComSupport::CMyListener::Create(
	IComEvtClient2* pEventMgr, 
	const CComPtr<IConnectionPoint>& spConnectionPoint,
	const CComPtr<IDispatch>& obj,
	DWORD dwObjID)
{
	m_dwObjID = dwObjID;
	m_pEventMgr = pEventMgr;
	HRESULT hr = CComObject<CMySink>::CreateInstance(&m_pListener);
	ASSERT(SUCCEEDED(hr));
	m_pListener->AddRef();

	try
	{
		hr = spConnectionPoint->Advise(m_pListener, &m_dwCockie);
	}
	catch(...)
	{
		ASSERT(FALSE);//Advise throws - very strange
		hr = E_FAIL;
	}

	if(FAILED(hr)|| m_dwCockie==0)
	{
		m_pListener->Release();
		m_pListener = NULL;
		return FALSE;
	}

	m_spConnectionPoint = spConnectionPoint;
	m_pListener->m_pEventMgr = this;

	//Advise is OK, now lets take the TypeInfo of the Connection

	hr = spConnectionPoint->GetConnectionInterface(&m_guid);
	if(FAILED(hr)|| m_guid==GUID_NULL)
	{
		m_guid=GUID_NULL;
		return TRUE;//bad GUID of the Connection,but we are Advised
	}

	CComPtr<ITypeInfo> spTi1;
	hr = obj->GetTypeInfo(0,0,&spTi1);
	if(FAILED(hr)|| spTi1==NULL) return TRUE;//bad TypeInfo from the COM Server ,but we are Advised

	CComPtr<ITypeLib> spTLib;
	hr = spTi1->GetContainingTypeLib(&spTLib,NULL);
	if(FAILED(hr)|| spTLib==NULL) return TRUE;//bad TypeLib( strange ),but we are Advised

	hr = spTLib->GetTypeInfoOfGuid(m_guid,&m_spTI);
	if(FAILED(hr)|| m_spTI==NULL)
	{
		m_spTI = NULL;
		return TRUE;//bad TypeInfo for the Connection,but we are Advised
	}

	hr = m_spTI->GetDocumentation(MEMBERID_NIL,m_strName.GetAddress(),NULL,0,NULL);
	//finally we have the name :)

	return TRUE;
}


HRESULT ComSupport::CMyListener::OnEvent(
            /* [in] */ DISPID dispIdMember,
            /* [in] */ REFIID riid,
            /* [in] */ LCID lcid,
            /* [in] */ WORD wFlags,
            /* [out][in] */ DISPPARAMS *pDispParams,
            /* [out] */ VARIANT *pVarResult,
            /* [out] */ EXCEPINFO *pExcepInfo,
            /* [out] */ UINT *puArgErr)
{
  DWORD i, k, t, buda_rem;
	_bstr_t strMethod;

	if(pDispParams == NULL || ObjectStore[m_dwObjID]==0 || Trace==2)
	  return E_POINTER;
  if((ObjectStore[m_dwObjID+8]&HALF)==0)
  {
	  if(my_strcmp(m_strName, make_long(StringStore+ObjectStore[m_dwObjID+8])))
	    return E_POINTER;
    Buda1[1]=TT_STR;
    Buda2[1]=ObjectStore[m_dwObjID+8];
	}
	else if(Buda1[1]!=TT_STR || my_strcmp(m_strName, make_long(StringStore+Buda2[1])))
	{
    Buda1[1]=TT_STR;
    i=ChangeCharset(M64_ch, ch_set, (BYTE *)(LPCTSTR)m_strName, StringStore+sv_StStore, &k, default_char);
    if (i) // must be made i>1
    {
      Buda2[1]=sv_StStore; 
      if ((sv_StStore+=i+1)>=STRING_STORE && correct_STR_ST() )
        goto FULL;
    }
    else
      Buda2[1]=0; 
	}
	//take the agruments and put them into array
  VARIANTARG *prgvarg            = pDispParams->rgvarg;
  DISPID     *prgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
  DWORD       ncArgs             = pDispParams->cArgs;
  DWORD       ncNamedArgs        = pDispParams->cNamedArgs;

	if(m_spTI !=NULL)
		m_spTI->GetDocumentation(dispIdMember,strMethod.GetAddress(),NULL,0,NULL);
//  else strMethod[0]=0;

  if (pVarResult) // need return
    Buda1[0]=TT_VAR; // clean for return
  else
    Buda1[0]=Definition[DF_GRAYED];
  buda_rem=buda_br;
  for(DWORD n=0; n<ncArgs; n++)
  {
    //myprgvarg = prgvarg + n;
    //CComVariant v(*myprgvarg);
    GetVariant(buda_br+n, prgvarg + n);
    //arr.Add(v);
  }
  if (ncArgs>=READY_LISTS && correct_ReadyLists(ncArgs))
    return S_OK; // not OK
  buda_br+=ncArgs;
  status_fl&=M1^4;
  a1=buda_br;
  Buda1[buda_br++]=ObjectStore[m_dwObjID+3];  // ms_function
  
  string[0]='\'';
  strcpy(string+1, make_short((LPCTSTR)strMethod));
  len=strlen(string);
  i_poin=0;
  f_end=len+3;
  strcpy(string+len, "'. ");
  if (read_n(&t, 2)==0 || t>=MEMORY_c256 || t==TT_VAR)
  {
    error=0;
    Buda1[buda_br]=TT_STR;
    i=ChangeCharset(M64_ch, ch_set, (BYTE *)(LPCTSTR)strMethod, StringStore+sv_StStore, &k, default_char);
    if (i)
    {
      Buda2[buda_br++]=sv_StStore;
      if ((sv_StStore+=i+1)>=STRING_STORE && correct_STR_ST() )
      {
FULL:   MessageBoxA(NUL, "The string store is full.", "No Space", MB_OK | MB_ICONSTOP);
        return S_OK; // not OK
      }
    }
    else
      Buda2[buda_br++]=0;
  }
  else
    Buda1[buda_br++]=t;
    
  Buda1[buda_br]=ReadyLists[ncArgs];
  Buda2[buda_br++]=sv_subv;
  for (i=0; i<ncArgs; Link[sv_subv++]=buda_rem+i++);
  my_gl+=ncArgs; //?

  i=stack_br;
  Stack[stack_br]|=HALF;
  Ekler[++ekler_br]=4*FIRST_ROWS-12; // -3
  Stack[stack_br+3]=ekler_br;
  my_gl2=FIRST_ROWS-3;
  DWORD j=call(2);
  if (j>1)
  {
    Wait_d=0;
    pMainFrame->PostMessage(WM_USER+1, j, 0); // OnEnd
  }
  else if (j==1)
  {
    for (DWORD m=i+3; m<stack_br; Stack[m+=4]|=HALF); // Cut
    call(1);
  }
  Stack[i]&=HALFM;
  status_fl|=4;
  if (Trace==1)
    MitiRedraw();
  for(DWORD t=0; t<ncArgs; t++)
  {
    SetVariant(buda_rem+t, prgvarg + t);
    //Buda1[buda_rem+t]=TT_VAR;
  }
  if (pVarResult) // need return
    SetVariant(0, pVarResult);
    
	//CArray<CComVariant,CComVariant&> arr;

	//take the name of the method if u can
#if TR
  MitiText((const char*)("from: " + m_strName+" method: "+ strMethod+"\r\n"));
#endif
	//notify Prolog
	//m_pEventMgr->OnEvent(m_dwObjID,m_strName,strMethod,arr);
	return S_OK;
}