#ifndef MODULE_OVER_SPEED_VEHICLE_H
#define MODULE_OVER_SPEED_VEHICLE_H
/**
  *@brief 车卡超速模块
  * @author 戴月腾
  * @date 2018-08-08
*/

#include <mutex>
#include <map>
#include <chrono>
#include <boost/thread.hpp>
#include <boost/enable_shared_from_this.hpp>
#include "module_const.h"

/**
 * @brief 区域超速类。当某张车卡速度超过某个区域的最大速度时,发出告警, 单例
 */
class module_over_speed_vehicle:public singleton_base<module_over_speed_vehicle>
{
private:
    friend class singleton_base<module_over_speed_vehicle>;
    module_over_speed_vehicle()
    {
    }

public:
    void on_hover(std::shared_ptr<card_location_base> card_ptr, int vehicle_category_id)
    {
        auto mine_tool_ptr = card_ptr->get_mine_tool();

        if(is_over_speed(vehicle_category_id, card_ptr->m_speed))//超速
        {
            mine_tool_ptr->m_over_speed_count++;
        }
        else//速度正常
        {
            mine_tool_ptr->m_normal_speed_count++;
        }

        //确定超速
        if(SPEED_COUNT_LIMIT <= mine_tool_ptr->m_over_speed_count)
        {
            mine_tool_ptr->m_over_speed_count=SPEED_COUNT_LIMIT;

            auto ev_ptr = event_list::instance()->get_event_card(card_ptr->m_id, card_ptr->m_type, ET_CARD_OVER_SPEED);
            if(ev_ptr)
            {
                event_list::copy_event(card_ptr, ev_ptr);

                ev_ptr->m_limit_value=limit_speed(vehicle_category_id);
                ev_ptr->m_cur_value=card_ptr->m_speed;
            }
            else//从没有告警状态转化为告警状态
            {
                mine_tool_ptr->m_normal_speed_count=0;

                auto ev_ptr = event_list::create_event_card(card_ptr->m_id, card_ptr->m_type, ET_CARD_OVER_SPEED);

                event_list::copy_event(card_ptr, ev_ptr);

                ev_ptr->m_limit_value = limit_speed(vehicle_category_id);
                ev_ptr->m_cur_value = card_ptr->m_speed;

                //保存到数据库
                event_list::save_event(ev_ptr);

                event_list::instance()->add(ev_ptr->get_list_id(),ev_ptr);

                log_info("车卡矿井内超速开始:卡id=%d,卡type=%d,卡速=%f,卡category_id=%d,卡速门限=%f",
                         card_ptr->m_id, card_ptr->m_type,card_ptr->m_speed,vehicle_category_id,
                         limit_speed(vehicle_category_id));
            }
        }

        //确定速度正常
        if(SPEED_COUNT_LIMIT <= mine_tool_ptr->m_normal_speed_count)
        {
            mine_tool_ptr->m_normal_speed_count=SPEED_COUNT_LIMIT;

            auto ev_ptr = event_list::instance()->get_event_card(card_ptr->m_id, card_ptr->m_type, ET_CARD_OVER_SPEED);
            if(ev_ptr && !ev_ptr->is_end())
            {
                mine_tool_ptr->m_over_speed_count=0;

                event_list::copy_event(card_ptr, ev_ptr);

                ev_ptr->m_limit_value = limit_speed(vehicle_category_id);
                ev_ptr->m_cur_value = card_ptr->m_speed;

                ev_ptr->m_status = ES_END;

                //保存到数据库
                event_list::save_event(ev_ptr);

                log_info("车卡矿井内超速结束:卡id=%d,卡type=%d,卡速=%f,卡category_id=%d,卡速门限=%f",
                         card_ptr->m_id, card_ptr->m_type,card_ptr->m_speed,vehicle_category_id,
                         limit_speed(vehicle_category_id));
            }
        }
    }

    void init_vehicle_category_from_db()
    {
        const char *sql = "SELECT vehicle_category_id, over_speed FROM dat_vehicle_category;";
        std::string Error;
        YADB::CDBResultSet DBRes;
        sDBConnPool.Query(sql,DBRes,Error);
        if(!Error.empty())
            log_error("init_vehicle_category Error,%s",Error.c_str());
        int64_t nCount = DBRes.GetRecordCount( Error );
        if (nCount < 1)
        {
            log_error("错误,init_vehicle_category. The record count=%ld\n", nCount );
            return;
        }

        log_info( "init_vehicle_category. The record count=%ld\n", nCount );

        _vehicle_category_map.clear();
        while ( DBRes.GetNextRecod(Error) )
        {
            int vehicle_category_id  = 0;
            DBRes.GetField( "vehicle_category_id",vehicle_category_id, Error );

            double over_speed = 0;
            DBRes.GetField( "over_speed",over_speed, Error );

            _vehicle_category_map.insert({vehicle_category_id,over_speed});
        }

        for(const auto &p : _vehicle_category_map)
            std_debug("dat_vehicle_category:category_id:%d--over_speed:%.2f",p.first,p.second);
    }

private:
    bool is_over_speed(int category_id, double speed)
    {
        auto serch = _vehicle_category_map.find(category_id);
        if(serch == _vehicle_category_map.end())
        {
            return false;
        }

        return serch->second <= speed;
    }

    double limit_speed(int category_id) const
    {
        auto serch = _vehicle_category_map.find(category_id);
        if(serch == _vehicle_category_map.end())
        {
            return 0;
        }

        return serch->second;
    }

private:
    std::unordered_map<int,double> _vehicle_category_map;
};

#endif // MODULE_OVER_SPEED_VEHICLE_H