#include "msg.h"
#include "opus_exceptions.h"

//////////////////////////////////////////////////////////////////////////
//
// Method: Event_iterator::Event_iterator
//
// Purpose:
//
//    The Event_iterator constructor.
//
// Description:
//
//    This method initializes the internal data structures used by the
//    iterator.
//
// Returns:
//
//    none
//
// Exceptions thrown:
//
//    none
//
// Example:
//
//    none
//
// Modification History:
//
// Date      OPR      Who         Reason
// --------- -------- ----------- ----------------------------------------
// 05/27/98  37796    WMiller     Initial code
//
//////////////////////////////////////////////////////////////////////////

template<class E, class EI>
Event_iterator<E, EI>::Event_iterator() : inited(false)
{
   // empty block
}

template<class E, class EI>
Event_iterator<E, EI>::Event_iterator(
                                      E& evt, // I - container type
                                      EI p)   // I - container iterator
                                      : inited(true), event_container(&evt),
                                        container_iterator(p)
{
   // empty block
}

//////////////////////////////////////////////////////////////////////////
//
// Method: Event_iterator::operator*
//
// Purpose:
//
//    Dereference the iterator.
//
// Description:
//
//    This method dereferences the iterator, returning a reference to the
//    underlying object.
//
// Returns:
//
//    A reference to the object pointed at by the iterator.
//
// Exceptions thrown:
//
//    Not_ready<void*> - if the iterator has not been initialized;
//                       Not_ready.arg is always zero.
//
// Example:
//
//    none
//
// Modification History:
//
// Date      OPR      Who         Reason
// --------- -------- ----------- ----------------------------------------
// 05/27/98  37796    WMiller     Initial code
// 07/29/03  41512    Sontag      Changes for gcc 3.2 on Solaris
//
//////////////////////////////////////////////////////////////////////////

template<class E, class EI>
typename Event_iterator<E, EI>::reference Event_iterator<E, EI>::operator*()
{
   if (!inited) {
      Msg m;
      m << sev(Msg::E) << type(Msg::MISUSE) <<
         "Event_iterator::operator* - Attempt to dereference uninitialized"
         " iterator." << endm;
      throw Not_ready<void*>(0);
   }
   return(*container_iterator);
}

//////////////////////////////////////////////////////////////////////////
//
// Method: Event_iterator::operator->
//
// Purpose:
//
//    Dereference the iterator.
//
// Description:
//
//    This method dereferences the iterator, returning a pointer to the
//    underlying object.
//
// Returns:
//
//    A pointer to the object pointed at by the iterator.
//
// Exceptions thrown:
//
//    Not_ready<void*> - if the iterator has not been initialized;
//                       Not_ready.arg is always zero.
//
// Example:
//
//    none
//
// Modification History:
//
// Date      OPR      Who         Reason
// --------- -------- ----------- ----------------------------------------
// 05/27/98  37796    WMiller     Initial code
// 07/29/03  41512    Sontag      Changes for gcc 3.2 on Solaris
//
//////////////////////////////////////////////////////////////////////////

template<class E, class EI>
typename Event_iterator<E, EI>::pointer Event_iterator<E, EI>::operator->()
{
   if (!inited) {
      Msg m;
      m << sev(Msg::E) << type(Msg::MISUSE) <<
         "Event_iterator::operator-> - Attempt to dereference uninitialized"
         " iterator." << endm;
      throw Not_ready<void*>(0);
   }
   return(&*container_iterator);
}

//////////////////////////////////////////////////////////////////////////
//
// Method: Event_iterator::operator++
//
// Purpose:
//
//    Advance iterator to the next item in the container.
//
// Description:
//
//    This method causes the iterator to point at the next item in the
//    container, or one past the last item in the container.
//
// Returns:
//
//    A reference to this object.
//
// Exceptions thrown:
//
//    Already<void*>   - if the iterator is at the end of the container;
//                       Already.arg is always zero.
//    Not_ready<void*> - if the iterator has not been initialized;
//                       Not_ready.arg is always zero.
//
// Example:
//
//    none
//
// Modification History:
//
// Date      OPR      Who         Reason
// --------- -------- ----------- ----------------------------------------
// 05/27/98  37796    WMiller     Initial code
//
//////////////////////////////////////////////////////////////////////////

template<class E, class EI>
Event_iterator<E, EI>& Event_iterator<E, EI>::operator++() // prefix++
{
   if (!inited) {
      Msg m;
      m << sev(Msg::E) << type(Msg::MISUSE) <<
         "Event_iterator::operator++ - Iterator is not initialized." << endm;
      throw Not_ready<void*>(0);
   }
   if (container_iterator == event_container->end()) {
      Msg m;
      m << sev(Msg::E) << type(Msg::MISUSE) <<
         "Event_iterator::operator++ - Iterator already at end." << endm;
      throw Already<void*>(0);
   }
   ++container_iterator;
   while (container_iterator != event_container->end() && !*container_iterator)
      ++container_iterator; // skip removed entries

   return *this;
}

template<class E, class EI>
Event_iterator<E, EI> Event_iterator<E, EI>::operator++(int) // postfix++
{
   Event_iterator<E, EI> tmp = *this;
   ++*this;
   return tmp;
}

//////////////////////////////////////////////////////////////////////////
//
// Method: Event_iterator::operator--
//
// Purpose:
//
//    Retreat iterator to the previous item in the container.
//
// Description:
//
//    This method causes the iterator to point at the previous item in the
//    container.
//
// Returns:
//
//    A reference to this object.
//
// Exceptions thrown:
//
//    Already<void*>   - if the iterator is at the beginning of the container;
//                       Already.arg is always zero.
//    Not_ready<void*> - if the iterator has not been initialized;
//                       Not_ready.arg is always zero.
//
// Example:
//
//    none
//
// Modification History:
//
// Date      OPR      Who         Reason
// --------- -------- ----------- ----------------------------------------
// 05/27/98  37796    WMiller     Initial code
//
//////////////////////////////////////////////////////////////////////////

template<class E, class EI>
Event_iterator<E, EI>& Event_iterator<E, EI>::operator--() // prefix--
{
   if (!inited) {
      Msg m;
      m << sev(Msg::E) << type(Msg::MISUSE) <<
         "Event_iterator::operator-- - Iterator is not initialized." << endm;
      throw Not_ready<void*>(0);
   }
   if (container_iterator == event_container->begin()) {
      Msg m;
      m << sev(Msg::E) << type(Msg::MISUSE) <<
         "Event_iterator::operator-- - Iterator already at beginning." << endm;
      throw Already<void*>(0);
   }
   --container_iterator;
   while (container_iterator != event_container->begin() && 
          !*container_iterator) --container_iterator; // skip removed entries

   return *this;
}

template<class E, class EI>
Event_iterator<E, EI> Event_iterator<E, EI>::operator--(int) // postfix--
{
   Event_iterator<E, EI> tmp = *this;
   --*this;
   return tmp;
}

//////////////////////////////////////////////////////////////////////////
//
// Method: Event_iterator::raw_iterator
//
// Purpose:
//
//    Get a copy of the basic iterator used by this object.
//
// Description:
//
//    This method returns a copy of the iterator type used by the
//    container.
//
// Returns:
//
//    An iterator type.
//
// Exceptions thrown:
//
//    Not_ready<void*> - if the iterator has not been initialized;
//                       Not_ready.arg is always zero.
//
// Example:
//
//    none
//
// Modification History:
//
// Date      OPR      Who         Reason
// --------- -------- ----------- ----------------------------------------
// 05/27/98  37796    WMiller     Initial code
//
//////////////////////////////////////////////////////////////////////////

template<class E, class EI>
EI Event_iterator<E, EI>::raw_iterator()
{
   if (!inited) {
      Msg m;
      m << sev(Msg::E) << type(Msg::MISUSE) <<
         "Event_iterator::raw_iterator - Iterator is not initialized." << endm;
      throw Not_ready<void*>(0);
   }
   return(container_iterator);
}

//////////////////////////////////////////////////////////////////////////
//
// Method: ::operator==
//
// Purpose:
//
//    Comparison operator for Event_iterator objects.
//
// Description:
//
//    This function compares two Event_iterator objects for equality.
//    The objects are equal if they point to the same container, and
//    the current value of their basic iterator types are the same.
//
// Returns:
//
//    true if the Event_iterator objects are equal.
//    false if the Event_iterator objects are not equal.
//
// Exceptions thrown:
//
//    none
//
// Example:
//
//    none
//
// Modification History:
//
// Date      OPR      Who         Reason
// --------- -------- ----------- ----------------------------------------
// 05/27/98  37796    WMiller     Initial code
//
//////////////////////////////////////////////////////////////////////////

template<class E, class EI>
bool operator==(
                const Event_iterator<E, EI>& i, // I - Event_iterator 1
                const Event_iterator<E, EI>& j) // I - Event_iterator 2
{
   return(i.event_container == j.event_container &&
          i.container_iterator == j.container_iterator);
}

//////////////////////////////////////////////////////////////////////////
//
// Method: ::operator!=
//
// Purpose:
//
//    Inequality operator for Event_iterator objects.
//
// Description:
//
//    This function compares two Event_iterator objects for inequality.
//    The objects are not equal if they point to different containers, or
//    the current value of their basic iterator types are not the same.
//
// Returns:
//
//    true if the Event_iterator objects are not equal.
//    false if the Event_iterator objects are equal.
//
// Exceptions thrown:
//
//    none
//
// Example:
//
//    none
//
// Modification History:
//
// Date      OPR      Who         Reason
// --------- -------- ----------- ----------------------------------------
// 05/27/98  37796    WMiller     Initial code
//
//////////////////////////////////////////////////////////////////////////

template<class E, class EI>
bool operator!=(
                const Event_iterator<E, EI>& i, // I - Event_iterator 1
                const Event_iterator<E, EI>& j) // I - Event_iterator 2
{
   return(!operator==(i, j));
}
