// MessageRoot.h : Declaration of the cMessageRoot

#ifndef __MESSAGEROOT_H_
#define __MESSAGEROOT_H_

#include "resource.h"       // main symbols

#include "MessageImpl.h"

/////////////////////////////////////////////////////////////////////////////
// cMessageRoot
class ATL_NO_VTABLE cMessageRoot : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<cMessageRoot, &CLSID_MessageRoot>,
   public IMessageIteratorImpl< cMessageRoot >
{
public:
	cMessageRoot()
	{
	}

   cMessage *m_pSource;

   cMessage *getSource()
   {
      return m_pSource;
   }

   DWORD getStartIndex()
   {
      return 0;
   }

   DWORD getEndIndex()
   {
      return m_pSource->m_fields.size();
   }

   DWORD getNextIndex()
   {
      if( m_nIndex != -1 )
         return getNextIndex( m_dwIterator );

      DWORD dwIterator = getStartIndex();

      while( dwIterator == m_pSource->m_fields.size() )
      {
         if( !m_pSource->loadNextElement() )
            return eEndIndex;
      }

      return dwIterator;
   }

   DWORD getNextIndex( DWORD dwIndex )
   {
      // Calculate the next index
      DWORD dwNextIndex = dwIndex + ( m_pSource->m_fields.begin() + dwIndex )->m_nOwns;

      // Insert this loop to make sure the cracking is done far enough ahead
      // This is a loop because it's entirely possible that loading a message element
      // will produce no fields (it's a rule that dosen't apply)
      while( dwNextIndex == m_pSource->m_fields.size() )
      {
         if( !m_pSource->loadNextElement() )
            return eEndIndex;
      }

      return dwNextIndex;
   }

   void init( cMessage *pSource )
   {
      m_pSource = pSource;
      IMessageIteratorImpl< cMessageRoot >::init();
   }

DECLARE_REGISTRY_RESOURCEID(IDR_MESSAGEROOT)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(cMessageRoot)
	COM_INTERFACE_ENTRY(IMessageIterator)
	COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

public:
};

#endif //__MESSAGEROOT_H_
