#include "area_business_speed_checker.h"

#include"event.h"
#include"common_tool.h"
#include"db/db_api/CDBSingletonDefine.h"
#include"log.h"

#include"area.h"
#include "card.h"

std::unordered_map<int,double> area_business_speed_checker::_vehicle_category_map;

struct over_speed_data:business_data
{
    over_speed_data()
    {
        m_over_speed_count=0;
        m_normal_speed_count=0;
        m_limit_speed=0;
        m_is_warning=false;
    }

    int m_over_speed_count;
    int m_normal_speed_count;
    double m_limit_speed;
    bool m_is_warning;
};
area_business_speed_checker::area_business_speed_checker()
{
}

void area_business_speed_checker::on_load_his(const std::shared_ptr<area_hover>&area_hover_ptr,
                                            const std::shared_ptr<card_location_base>&card_ptr,std::shared_ptr<business_data>&ptr)
{
    on_enter(area_hover_ptr, card_ptr, ptr);
}

void area_business_speed_checker::on_enter(const std::shared_ptr<area_hover>&area_hover_ptr,
                                           const std::shared_ptr<card_location_base>&card_ptr,std::shared_ptr<business_data>&ptr)
{
    if(!card_ptr->is_vehicle())
    {
        return;
    }

    auto ptr_temp = std::make_shared<over_speed_data>();
    ptr = ptr_temp;
    area_hover_ptr->m_data[area_business_type()] = ptr_temp;

    double limit = area_hover_ptr->m_area->m_over_speed_vehicle;
    if(area_hover_ptr->m_area->is_mine())
    {
        limit = _get_mine_limit_speed(card_ptr->get_vehicle_category_id());
    }

    if(limit < 0.01)
    {
        return;
    }

    ptr_temp ->m_limit_speed = limit;
    if(limit < card_ptr->m_speed)
    {
        ptr_temp->m_over_speed_count++;
    }
    else
    {
        ptr_temp->m_normal_speed_count++;
    }

    EVENT_TYPE ev_type = ET_CARD_AREA_OVER_SPEED;
    if(area_hover_ptr->m_area->is_mine())
    {
        ev_type = ET_CARD_OVER_SPEED;
    }
    auto ev_ptr_temp = event_list::instance()->get_event_card(card_ptr->m_id, card_ptr->m_type, ev_type);
    ptr_temp->m_is_warning = (nullptr != ev_ptr_temp && !ev_ptr_temp->is_end());
}

void area_business_speed_checker::on_hover(const std::shared_ptr<area_hover>&area_hover_ptr,
                                           const std::shared_ptr<card_location_base>&card_ptr,std::shared_ptr<business_data> ptr)
{
    if(!card_ptr->is_vehicle())
    {
        return;
    }
    if(nullptr == ptr)
    {
        log_error("area_business_speed_checker::on_hover：nullptr == ptr");
        return;
    }

    auto ptr_temp = static_cast<over_speed_data*>(ptr.get());
    double limit = ptr_temp ->m_limit_speed;
    if(limit < 0.01)
    {
        return;
    }

    if(limit < card_ptr->m_speed)//超速
    {
        ptr_temp->m_over_speed_count++;
        ptr_temp->m_normal_speed_count=0;
    }
    else//速度正常
    {
        ptr_temp->m_normal_speed_count++;
        ptr_temp->m_over_speed_count=0;
    }

    EVENT_TYPE ev_type = ET_CARD_AREA_OVER_SPEED;
    if(area_hover_ptr->m_area->is_mine())
    {
        ev_type = ET_CARD_OVER_SPEED;
    }

    //确定告警
    if(SPEED_COUNT_LIMIT <= ptr_temp->m_over_speed_count)
    {
        ptr_temp->m_over_speed_count=SPEED_COUNT_LIMIT;

        if(!ptr_temp->m_is_warning)
        {
            ptr_temp->m_is_warning = true;

            uint64_t id = tool_other::type_id_to_u64(card_ptr->m_type, card_ptr->m_id);
            event_tool::instance()->handle_event(OT_CARD, ev_type, id, limit, card_ptr->m_speed, true);
        }
    }

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

        if(ptr_temp->m_is_warning)
        {
            ptr_temp->m_is_warning=false;

            uint64_t id = tool_other::type_id_to_u64(card_ptr->m_type, card_ptr->m_id);
            event_tool::instance()->handle_event(OT_CARD, ev_type, id, limit, card_ptr->m_speed, false);
        }
    }
}

void area_business_speed_checker::on_leave(const std::shared_ptr<area_hover>&area_hover_ptr,
                                           const std::shared_ptr<card_location_base>&card_ptr,std::shared_ptr<business_data> ptr)
{
    if(!card_ptr->is_vehicle())
    {
        return;
    }
    if(nullptr == ptr)
    {
        log_error("area_business_speed_checker::on_leave：nullptr == ptr");
        return;
    }

    auto ptr_temp = static_cast<over_speed_data*>(ptr.get());
    double limit = ptr_temp ->m_limit_speed;

    EVENT_TYPE ev_type = ET_CARD_AREA_OVER_SPEED;
    if(area_hover_ptr->m_area->is_mine())
    {
        ev_type = ET_CARD_OVER_SPEED;
    }

    uint64_t id = tool_other::type_id_to_u64(card_ptr->m_type, card_ptr->m_id);
    event_tool::instance()->handle_event(OT_CARD, ev_type, id, limit, card_ptr->m_speed, false);
}

void area_business_speed_checker::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);
}


