/* events.cpp
 */


#include <iostream.h>
#include <stdlib.h>
#include "events.H"
#include "person.H"
#include "elevator.H"
#include "floor.H"
#include "main.H"
#include "graphics.H"
#include "sched.H"
#include "stats.H"

int
Event::compare(Event *e1, Event *e2)
{
    return e1->time >= e2->time;
}


/* An elevator arrival: Call the handler and notify the controller of
 * the arrival so that it may schedule the next arrival of this
 * elevator.
 */

void
ElevatorArrival::handle_event() 
{
    if (text_output) {
	cout << current_time << ": Elevator ";
	elevator->print();
	cout << " arrives on floor ";
	floor->print();
	cout  << "\n";
    }

    if (redraw_upon_event)
	graphics.draw_all();

    elevator->handle_arrival_at_floor( floor );
    controller->schedule_next_departure( elevator );
}


/* An elevator departure: Simply schedule the elevator's next arrival.
 */

void
ElevatorDeparture::handle_event() 
{
    if (text_output) {
	cout << current_time << ": Elevator ";
	elevator->print();
	cout << " leaves\n";
    }

    if (redraw_upon_event)
	graphics.draw_all();

    elevator->handle_departure_from_floor();
    controller->schedule_next_arrival( elevator, dest_floor );
}


/* A person appears: Create the person, call the handler, and schedule
 * the next appearance.
 */

void 
PersonAppearance::handle_event()
{
    Person *person;
    double rand_val = (double)rand()/RAND_MAX;
    int p;
    float sum = 0;
    PersonType ptype;

    for(p = 0; p < NUMTYPES; p += 1) {
      sum += Person_Distribution[p];
      if(rand_val <= sum) {
	ptype = p;
	break;
      }
    }

    switch (ptype) {
    case NORMAL : 
	person = new Person;
	if (text_output) {
	    cout << current_time << ": Person ";
	    person->print();
	}
	break;
    case IMPATIENT : 
	person = new ImpatientPerson(source_floor); 
	if (text_output) {
	    cout << current_time << ": Impatient Person ";
	    person->print();
	}
	break;
    default : cout << "ERROR: Bogus person type, creating a normal person\n";
      person = new Person; break;
    }
    
    
    if (text_output) {
	cout << " appears on floor ";
	source_floor->print();
	cout << " to go to floor ";
	dest_floor->print();
	cout << "\n";
    }

    if (redraw_upon_event)
	graphics.draw_all();

    person->handle_initial_appearance( source_floor, dest_floor );
    source_floor->schedule_next_appearance();
}

void
PersonLeave::handle_event()
{
    floor->remove_person( person );
    statistics.report_impatient_departure( person );
    delete person;
    
}


/* A report: Just call the draw_all() routine.
 */

void
ReportEvent::handle_event()
{
    ReportEvent *event;

    if (redraw_regularly)
	graphics.draw_all();

    if (!text_output)
	statistics.periodic_report();

    event = new ReportEvent( current_time + report_interval );
    scheduler.add_event( event );
}
