/*

 BabbleMud - A MUD server

 Author:  Nick Gammon 
          http://www.gammon.com.au/ 

(C) Copyright Nick Gammon 2004. Permission to copy, use, modify, sell and
distribute this software is granted provided this copyright notice appears
in all copies. This software is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.
 
*/

 /*

  event management class

  Author: Nick Gammon 
  Date:   20th July 2003

*/

#include "events.h"

#ifdef WIN32
#include <Windows.h>
#include <time.h>
#else
#include <sys/time.h>
#endif

#include <iostream>

// 1. pull out events from the event queue
// 2. keep going until one is due in the future
// 3, if rescheduling wanted keep in temporary vector until all are done

void ProcessEvents (EventQueue & queue, EventHandler handler)
  {
  int now = GetMillisecondsTime ();
  vector<Event> repeated_events;

  // pull out event that need doing
  while (!queue.empty ())
    {
    Event e = queue.top ();

    if (e.GetTime () > now)
      break;  // not yet

    queue.pop ();  // remove from queue

    e.Fired ();    // note it fired
    handler (e);   // handle it
    
    // if repeating it wanted, recalculate and keep in separate list
    // note: -1 means keep firing indefinitely, 1 or more means keep going until zero
    if (e.GetCount () != 0)
      {
      e.Reschedule ();
      repeated_events.push_back (e);
      }

    }  // end of event loop

  // put any event we rescheduled back into the queue
  // we do it now so we don't get into a loop if the event is due to
  // fire immediately
  // do it backwards so the last one off is the first one back
  copy (repeated_events.rbegin (),
        repeated_events.rend (),
        event_queue_back_inserter (queue));
  
  } // end of ProcessEvents 


// thanks to Ksilyan for this routine :)
const int GetMillisecondsTime ()
  {
#ifdef WIN32
  #pragma comment( lib, "winmm.lib" ) // this is the library it is in

  // Under Windows, the time is the time since system startup.
  // Knowing Billysoft, this'll never be more than 5 minutes *wink*
  // but seriously, we don't need to worry about overflow here
                
   return timeGetTime();
#else
  struct timeval resultTimeval;
  gettimeofday( &resultTimeval, NULL );

  // First off... tv_sec is seconds since the Epoch
  // this is generally Jan 1st 1970.
  // now we don't want to multiply this by 1000, since
  // it might overflow... so first, subtract the seconds
  // from jan-1-1970 to jan-1-2000

  resultTimeval.tv_sec -= 946080000; // 30 years
  return resultTimeval.tv_sec * 1000 + resultTimeval.tv_usec / 1000;
#endif
  }  // end of GetMillisecondsTime
