/* File: network.h
 *
 * The necessary classes for the street network.  The network will consist 
 * of streets, intersections and traffic lights.
 */

#define NOT_A_STREET		-1

/* Street: A street is section of a road between two intersections. */
/*------------------------------------------------------------------*/
class Street {
    public:
        int from;              // the street goes from this intersection
        int to;                //   and to this intersection
        int speed;             // # of cars that may traverse per clock tick
        int length;            // clock ticks it takes to travel the street
        int load;              // how busy is the street
        int capacity;          // max # of cars that street can hold at one time
        Queue *queue;          // used to hold the cars on the street
        Street() { queue = 0; }
        ~Street() { if (queue) delete queue; }
};

struct Intersection;          // these are defined below
class TrafficLight;

/* The Network is the full collection of streets and intersections */
/*-----------------------------------------------------------------*/
class Network {
    public:
                // add a new street from x to y into the network
        void add_street(int x, int y, int length, int capacity, int speed);

                // add information on intersection x
        void add_intersection(int x, int north, int east, int south, int west);

                // return the number of intersections
        int get_size() { return num_intersections; }

                // return the number of streets
        int number_streets() { return num_streets; }

                // return the shortest path from x to y in the network
        int get_shortest_path(int x, int y, int *return_path);

                // start running the network - the start_time is given
        void start(int start_time);

                // update the network to the given time
        void update(int time);

                // add a car to the street
        bool add_to_street(int car_id, Street *street);

                // returns whether the traffic light is green for this street
        bool light_is_green(Street *street);

                // return the head car on the street
        bool next_to_go(Street *street, int *car_id);

                // return the next car to leave the street
        bool remove_from_street(Street *street, int *car_id);

                // get the street object for street number i
        Street *get_street(int i) { return street_array[i]; }

                // get the street that runs from x to y
        Street *get_street(int x, int y) { return &streets[x][y]; }

                // return the speed of a street
        int street_speed(Street *street) { return street->speed; }

                // return the length of a street
        int street_length(Street *street) { return street->length; }

                // where the street runs to
        int street_to(Street *street) { return street->to; }

                // where the street runs from
        int street_from(Street *street) { return street->from; }

        Network(int size);
        ~Network();

    private:
        int num_intersections;        // # of intersections in network
        int num_streets;              // # of streets in network
        bool graph_modified;          // have we modified the underlying graph?
        Graph *graph;                 // the underlying graph
        Street **streets;             // different ways to acccess streets so
        Street **street_array;        // streets is 2D and street_array is 1D
        Intersection *intersections;  // an array of the intersections
};

/* Traffic Lights exist at each intersection and control which cars may leave */
/*     their respective streets.  Currently a light has 4 states in a cycle:  */
/*     one side is green, all are red, other side is green, all are red.      */
/*     Yellow lights are ignored.                                             */
/*----------------------------------------------------------------------------*/
#define MAX_STATES 4                  // number of states in a light cycle
#define MAX_NEIGHBORS 4               // max streets at an intersection
#define ALL_RED_TIME 4                // pause one side's red til other's green

class TrafficLight {
    public:
                         // is the light green for the street from x?
        bool is_green(int x);

                         // place cycle in a random state
        void random_cycle(int time);

                         // update the light to the entered time
        void update_light(int time);

                         // set the streets at the light and the length of cycle
        void initialize_light(int north, int east, 
                              int south, int west, int cycle);

    private:                                // the state names
        enum state {ALL_RED_1 = 0, EVEN_GREEN, ALL_RED_2, ODD_GREEN};
        int cycle_length;                   // length of cycle in clock ticks
        int cycle_times[MAX_STATES];        // length of each state of cycle
        state current_state;                // the current state of cycle
        int next_change;                    // time when state will change
        int neighbors[MAX_NEIGHBORS];       // the incoming streets, the index
                                            //    of the "from" intersections
};

/* An Intersection of our network.  Currently, all we care about an */
/* intersection is that it has a traffic light.                     */
/*------------------------------------------------------------------*/
struct Intersection {
    TrafficLight light;
};


