/*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  Method:   tLuaCOMConnPointContainer
              ::tLuaCOMConnPointContainer

  Summary:  Constructor for the tLuaCOMConnPointContainer interface
            instantiation.

  Args:     COBall* pBackObj,
              Back pointer to the parent outer object.
            IUnknown* pUnkOuter
              Pointer to the outer Unknown.  For delegation.

  Modifies: pBackObj, pUnkOuter.

  Returns:  void
M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
tLuaCOMConnPointContainer::tLuaCOMConnPointContainer(lua_State* p_L,
                                                     IUnknown* p_pUnkOuter)
{
  HRESULT hr = S_OK;
  ITypeInfo *events_typeinfo = NULL;

  CHECKPARAM(p_L); CHECKPARAM(p_pUnkOuter);

  // stores pointers
  pUnkOuter = p_pUnkOuter;
  L = p_L;

  // creates connection point for source interface
  IProvideClassInfo2 *ci2  = NULL;

  hr = pUnkOuter->QueryInterface(IID_IProvideClassInfo2, (void **) &ci2); 
  CHK_COM_CODE(hr);

  IID iid;

  hr = ci2->GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID, &iid);
  CHK_COM_CODE(hr);

  ITypeInfo *coclassinfo = NULL;

  hr = ci2->GetClassInfo(&coclassinfo);
  CHK_COM_CODE(hr);  

  events_typeinfo = tCOMUtil::GetDefaultInterfaceTypeInfo(coclassinfo, true);
  CHK_LCOM_ERR(events_typeinfo, "No default source typeinfo.");

  COM_RELEASE(ci2);
  COM_RELEASE(coclassinfo);

  max_connection_points = 1;
  connection_points = new tLuaCOMConnPoint*[max_connection_points];
  CHKMALLOC(connection_points);

  connection_points[0] = new tLuaCOMConnPoint(L, p_pUnkOuter);
  CHKMALLOC(connection_points[0]);

  connection_points[0]->AddRef();
  
  num_connection_points = 1;

  hr = connection_points[0]->Init(iid, events_typeinfo);
  CHK_COM_CODE(hr);  

  default_connection = connection_points[0];

  return;
}
int tLuaCOMEnumerator::callCOMmethod(lua_State* L, const char *name, int first_param, int num_params)
{
  HRESULT hr = S_OK;

  // Next method
  if(strcmp(name, "Next") == 0)
  {
    VARIANT* pVar = NULL;
    unsigned long num_elements = 1, counter = 0;
    ULONG fetched = 0;


    if(num_params > 0)
    {
      num_elements = (unsigned long) lua_tonumber(L, first_param);
    }

    pVar = new VARIANT[num_elements];

    for(counter = 0; counter <  num_elements; counter++)
      VariantInit(&pVar[counter]);


    hr = pEV->Next(num_elements, pVar, &fetched);
    
    for(counter = 0; counter < fetched; counter++)
    {
      typehandler->com2lua(L, pVar[counter]);
      typehandler->releaseVariant(&pVar[counter]);
    }

    for(counter = 0; counter <  num_elements; counter++)
	  VariantClear(&pVar[counter]);

    delete[] pVar;

	pVar = NULL;

    return fetched;
  }

  if(strcmp(name, "Reset") == 0)
  {
    hr = pEV->Reset();
    CHK_LCOM_ERR(hr == S_OK, "Unable to reset enumeration.");
    
    return 0;
  }

  if(strcmp(name, "Skip") == 0)
  {
    CHK_LCOM_ERR(num_params > 0, "Not enough parameters.");

    unsigned long num_elements = (unsigned long) lua_tonumber(L, first_param);

    hr = pEV->Skip(num_elements);

    luaCompat_pushBool(L, hr == S_OK);

    return 1;
  }

  if(strcmp(name, "Clone") == 0)
  {
    IEnumVARIANT* p_newEV = NULL;

    hr = pEV->Clone(&p_newEV);
    CHK_COM_CODE(hr);

    tLuaCOMEnumerator* enumerator = new tLuaCOMEnumerator(p_newEV);
    
    COM_RELEASE(p_newEV);

    enumerator->push(L);

    return 1;
  }



  return 0;
}