/*-------------------------------------------------------------------------
 * fedsrv\AdminUsers.CPP
 * 
 * Implementation of CAdminUsers
 * 
 * Owner: 
 * 
 * Copyright 1986-1999 Microsoft Corporation, All Rights Reserved
 *-----------------------------------------------------------------------*/

#include "pch.h"


/////////////////////////////////////////////////////////////////////////////
// CAdminUsers

TC_OBJECT_EXTERN_NON_CREATEABLE_IMPL(CAdminUsers)


/////////////////////////////////////////////////////////////////////////////
// ISupportErrorInfo Interface Methods

STDMETHODIMP CAdminUsers::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] = 
	{
		&IID_IAdminUsers
	};
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}




CAdminUsers::CAdminUsers() :
    m_pIGCmission(NULL)
{
}


CAdminUsers::~CAdminUsers()
{
}

      



/*-------------------------------------------------------------------------
 * get_Count()
 *-------------------------------------------------------------------------
 * Purpose:
 *    For some internal VB script stuff.
 *
 * Returns:
 *    pnCount: the size of the collection (in elements)
 * 
 */
STDMETHODIMP CAdminUsers :: get_Count(long* pnCount)
{
  *pnCount = 0;

  long i = 0;

  if (m_pIGCmission)
  {
    const ShipListIGC * plistShip = m_pIGCmission->GetShips();

    //
    // Iterate thru all ships in mission
    //
    for(ShipLinkIGC * plinkShip = plistShip->first(); plinkShip; plinkShip = plinkShip->next())
    {
      CFSShip * pfsShip = (CFSShip *) plinkShip->data()->GetPrivateData();
      if (pfsShip->IsPlayer())
        ++i;
    }

    *pnCount = i;
  }
  else
  {
    *pnCount = (long)g.pServerCounters->cPlayersOnline;
  }

  // Indicate success
  return S_OK;
}



/*-------------------------------------------------------------------------
 * get__NewEnum()
 *-------------------------------------------------------------------------
 * Purpose:
 *    Provide iteration support for things (like VB/Javascript languages) 
 *    that use this COM object.
 */
STDMETHODIMP CAdminUsers :: get__NewEnum(IUnknown** ppunkEnum)
{
  // Clear the [out] parameter
  CLEAROUT(ppunkEnum, (IUnknown*)NULL);

  // Create a new CComEnum enumerator object
  typedef CComObject<CComEnum<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT,
    _Copy<VARIANT> > > CEnum;
  CEnum* pEnum = new CEnum;
  assert(NULL != pEnum);

  //
  // Copy the pCAdminGame elements into to a temporary CComVariant vector
  //

  long cTotal;
  get_Count(&cTotal);

  CComVariant* pargTemp = new CComVariant[cTotal];

  long i = 0;

  if (m_pIGCmission)
  {
    //
    // Iterate thru all ships in mission
    //
    for(ShipLinkIGC * plinkShip = m_pIGCmission->GetShips()->first(); plinkShip; plinkShip = plinkShip->next())
    {
      CFSShip * pfsShip = (CFSShip *) plinkShip->data()->GetPrivateData();
      if (pfsShip->IsPlayer())
      {
        CFSPlayer * pfsPlayer = pfsShip->GetPlayer();

        IAdminUser *pIAdminUser;

        RETURN_FAILED (pfsPlayer->CAdminSponsor<CAdminUser>::Make(IID_IAdminUser, (void**)&pIAdminUser));

        pfsPlayer->CAdminSponsor<CAdminUser>::GetLimb()->Init(pfsPlayer);

        pargTemp[i] = pIAdminUser;

        ++i;

        // at this point we now we are done.  This is not only an optimization but
        // a safeguard incase IGC is flawed.
        if (i >= cTotal) 
            break;
      }
    }
  }
  else
  {
      //
      // Iterate thru all missions
      //
      const ListFSMission * plistMission = CFSMission::GetMissions();
      for (LinkFSMission * plinkMission = plistMission->first(); plinkMission; plinkMission = plinkMission->next())
      {
            CFSMission * pfsMission = plinkMission->data();

            ImissionIGC * pIGCmission = pfsMission->GetIGCMission();

            const ShipListIGC * plistShip = pIGCmission->GetShips();

            //
            // Iterate thru all ships in mission
            //
            for(ShipLinkIGC * plinkShip = plistShip->first(); plinkShip; plinkShip = plinkShip->next())
            {
              CFSShip * pfsShip = (CFSShip *) plinkShip->data()->GetPrivateData();
              if (pfsShip->IsPlayer())
              {
                CFSPlayer * pfsPlayer = pfsShip->GetPlayer();

                IAdminUser *pIAdminUser;

                RETURN_FAILED (pfsPlayer->CAdminSponsor<CAdminUser>::Make(IID_IAdminUser, (void**)&pIAdminUser));

                pfsPlayer->CAdminSponsor<CAdminUser>::GetLimb()->Init(pfsPlayer);

                pargTemp[i] = pIAdminUser;

                ++i;

                // at this point we now we are done.  This is not only an optimization but
                // a safeguard incase IGC is flawed.
                if (i >= cTotal) goto exit_loops;
              }
          }
      }
  }

exit_loops:


  // Initialize enumerator object with the temporary CComVariant vector
  HRESULT hr = pEnum->Init(&pargTemp[0], &pargTemp[cTotal], NULL, AtlFlagCopy);

  delete [] pargTemp;

  if (SUCCEEDED(hr))
    hr = pEnum->QueryInterface(IID_IEnumVARIANT, (void**)ppunkEnum);
  if (FAILED(hr))
    delete pEnum;


  // Return the last result
  return hr;
}



/*-------------------------------------------------------------------------
 * get_Item()
 *-------------------------------------------------------------------------
 * Purpose:
 *         
 * Remarks:
 *   This is not supported because it would be O(n) time for something that
 *   usually takes O(1) time.  Also, since this is a multi-process envirnoment
 *   an index in not constant.
 */
STDMETHODIMP CAdminUsers :: get_Item(VARIANT index, IAdminUser** ppUser)
{
  *ppUser = NULL;

//  // Attempt to convert the specified VARIANT to a long
//  CComVariant var;
//  HRESULT hr = VariantChangeType(&var, &index, 0, VT_I4);
//  if (FAILED(hr))
//    return hr;
//  const int iIndex(V_I4(&var));

  return Error("get_Item[] is intentionally not supported; use FOR...EACH instead.");
}