/*
 *  TnTrafficSpeedIcon.h
 *
 *  Created by Thant on Octobor 29, 2013.
 *  Copyright 2013 TeleNav. All rights reserved.
 */

#ifndef TN_TRAFFIC_SPEED_ICON_INCLUDED
#define TN_TRAFFIC_SPEED_ICON_INCLUDED

#include <set>
#include <boost/optional.hpp>

struct TnTrafficSpeedIcon
{
    TnTrafficSpeedIcon(std::string const & id,
                       Tn::math::Point2d const & location,
                       double speed,
                       double free_flow,
                       std::string level);

    std::string id;     // not sure we need this
    Tn::math::Point2d location;
    double speed;       // in meters per second
    double free_flow;
    std::string level;  // i.e. "CONGESTED"

    /*  So the definition is in one place only:  */

#if 0
    static inline double delay(double free_flow, double speed) {return free_flow - speed;}
#else
    static inline double delay(double free_flow, double speed) {
        return (free_flow==0.0) ? 0.0 : (1.0 - speed/free_flow);
    }
#endif

    inline double delay() const {return delay(free_flow,speed);}
};

// Order based on delay
bool operator<(TnTrafficSpeedIcon const & a, TnTrafficSpeedIcon const & b);

enum eTnSpeedUnits {
    eTnSpeedUnits_English,         // miles per hour
    eTnSpeedUnits_Metric           // kilometers per hour
};

double fromMetersPerSecond(double meters_per_second, eTnSpeedUnits units);
double toMetersPerSecond(double kph_or_mph, eTnSpeedUnits units);

/*  This keeps track of a fixed number of the slowest traffic flows.
 *
 *  Should this be abstracted?
 */

struct TnLowFlowHeap 
{
    TnLowFlowHeap(uint32_t max_size);   

    /*  Only pushes if new icon has a bigger delay than the smallest
     *  delay that is already in the heap, or if the heap hasn't
     *  exceeded max size.
     */

    void push(TnTrafficSpeedIcon const &);

    /* Pops from largest delay to smallest delay. */
    boost::optional<TnTrafficSpeedIcon> pop();

    /*  This returns the speed of the least delayed item. If a traffic
     *  speed icon has a smaller delay than this, there's no point in
     *  pushing it.
     */
    double smallestDelay();

private:

    /* It behaves like a heap sort, but I'm using a set. */

    typedef std::set<TnTrafficSpeedIcon> Set;

    Set m_set;
    uint32_t m_max_size;
};


#endif
