#include "event.h"
#include "area.h"
#include "card_base.h"
#include "common_tool.h"
#include "log.h"

#include "area_business_count_checker.h"
/*
	判断当前区域a中的人数是否超过设定人数,超过后告警
	区域内实时人数存储在area对象中,在当前类on_enter/on_leave中进行更新
	整个井下的超员和某个区域的超员都使用这个代码
*/

static void check_event(bool &event_flag,EVENT_TYPE et,EVENT_DIS_TYPE edt,int id)
{
    if(!event_flag)
    {
        auto ev_p = event_list::instance()->get_event_area(id,et,edt);
        if (ev_p && !ev_p->is_end())
            event_flag = true;
    }
}

//服务器重启加载数据
void area_business_count_checker::on_load_his(const std::shared_ptr<area_hover>&a,const std::shared_ptr<card_location_base>&c,std::shared_ptr<business_data>&ptr)
{
    if (nullptr == a->m_area )
        return ;
    if (c->is_person())
    {
        EVENT_TYPE ev = a->m_area->is_mine()?EVENT_TYPE::ET_OVER_COUNT_PERSON : EVENT_TYPE::ET_AREA_OVER_COUNT_PERSON ;
        check_event(a->m_area->m_event_person_count,ev,DT_NORMAL,a->m_area->id());
        check_event(a->m_area->m_event_person_show_count,ev,DT_SPECIAL,a->m_area->id());
    }
    else if (c->is_vehicle())
    {
        EVENT_TYPE ev = a->m_area->is_mine()?EVENT_TYPE::ET_OVER_COUNT_VEHICLE : EVENT_TYPE::ET_AREA_OVER_COUNT_VEHICLE ;
        check_event(a->m_area->m_event_vehicle_count,ev,DT_NORMAL,a->m_area->id());
        check_event(a->m_area->m_event_vehicle_show_count,ev,DT_SPECIAL,a->m_area->id());
    }
    on_enter(a,c,ptr);
}
//增加计数,并进行判断
//多线程环境有可能同时产生相同的告警。
//如果多个线程同一时间触发。
void area_business_count_checker::on_enter(const std::shared_ptr<area_hover>&a,
                                           const std::shared_ptr<card_location_base>&c,std::shared_ptr<business_data>&ptr)
{
	if (nullptr == a->m_area )
		return ;
	if (c->is_person())
	{
        int limit_val=a->m_area->m_limit_person_count;
        int aid=a->m_area->id();
        if(limit_val<=0)
        {
            log_warn("on_enter_area_id:%d,limit_person_count is 0.so should not run area_business_count_checker...",aid);
            return;
        }
        if(!ptr)
		    a->m_area->m_person_count ++;
        if(c->m_display)
		    a->m_area->m_person_show_count ++ ;
        int pc=a->m_area->m_person_count.load();
        int pc_=a->m_area->m_person_show_count.load();
	    EVENT_TYPE ev = a->m_area->is_mine()?EVENT_TYPE::ET_OVER_COUNT_PERSON : EVENT_TYPE::ET_AREA_OVER_COUNT_PERSON ;
        if(pc>limit_val){
            lock();
		    event_tool::instance()->handle_event(OT_AREA,ev,aid,limit_val,pc,a->m_area->m_event_person_count=true,DT_NORMAL);
            unlock();
		    log_info("person_count_enter:%d,v_count:%d limit:%d",aid,pc,limit_val);
        }
        if(pc_>limit_val){
            lock();
		    event_tool::instance()->handle_event(OT_AREA,ev,aid,limit_val,pc_,a->m_area->m_event_person_show_count=true,DT_SPECIAL);
            unlock();
		    log_info("person_count_enter_show:%d,v_count:%d limit:%d",aid,pc_,limit_val);
        }
	}
	else if (c->is_vehicle())
	{
        int limit_val=a->m_area->m_limit_vehicle_count;
        int aid=a->m_area->id();
        if(limit_val<=0)
        {
            log_warn("on_enter_area_id:%d,limit_vehicle_count is 0.so should not run area_business_count_checker...",aid);
            return;
        }
        if(!ptr)
		    a->m_area->m_vehicle_count ++ ;
        if(c->m_display)
		    a->m_area->m_vehicle_show_count ++ ;
        int vc=a->m_area->m_vehicle_count.load();
        int vc_=a->m_area->m_vehicle_show_count.load();
		EVENT_TYPE ev = a->m_area->is_mine()?EVENT_TYPE::ET_OVER_COUNT_VEHICLE : EVENT_TYPE::ET_AREA_OVER_COUNT_VEHICLE ;
        if(vc>limit_val){
            lock();
		    event_tool::instance()->handle_event(OT_AREA,ev,aid,limit_val,vc,a->m_area->m_event_vehicle_count=true,DT_NORMAL);
            unlock();
		    log_info("vehicle_count_enter:%d,v_count:%d limit:%d",aid,vc,limit_val);
        }
        if(vc_>limit_val){
            lock();
		    event_tool::instance()->handle_event(OT_AREA,ev,aid,limit_val,vc_,a->m_area->m_event_vehicle_show_count=true,DT_SPECIAL);
            unlock();
		    log_info("vehicle_count_enter_show:%d,v_count:%d limit:%d",aid,vc_,limit_val);
        }
	}
    c->update_display();
}
void area_business_count_checker::on_hover(const std::shared_ptr<area_hover>&a,
                                           const std::shared_ptr<card_location_base>&c,std::shared_ptr<business_data> ptr)
{
    if(!c->eq_display())
    {
        ptr=std::make_shared<business_data>();
        if(c->m_display==1)
          on_enter(a,c,ptr);
        else if(c->m_display==0)
          on_leave(a,c,ptr);
        c->update_display();
        ptr=nullptr;
    }
}

//减少计数
void area_business_count_checker::on_leave(const std::shared_ptr<area_hover>&a,
                                           const std::shared_ptr<card_location_base>&c,std::shared_ptr<business_data> ptr)
{
	if (nullptr == a->m_area )return ;
    int flag=c->m_display;
    if(!ptr){
        if(!c->eq_display()){
            c->update_display(); 
            //从0 变成1 之前是0 m_show_count没加1 这里不需要减一
            if(c->m_display==1)flag=0;
            //从1 变成 0 之前是加1了。 这里需要减去
            if(c->m_display==0)flag=1;
        }
    }
	if (c->is_person())
	{
        if(ptr)
		    a->m_area->m_person_show_count -- ;
        else{
		    a->m_area->m_person_count -- ;
            //if(c->m_display)
            if(flag)
		        a->m_area->m_person_show_count -- ;
        }
        int pc=a->m_area->m_person_count.load();
        int pc_=a->m_area->m_person_show_count.load();
        int limit_val=a->m_area->m_limit_person_count;
        int aid=a->m_area->id();
	    EVENT_TYPE ev = a->m_area->is_mine()?EVENT_TYPE::ET_OVER_COUNT_PERSON : EVENT_TYPE::ET_AREA_OVER_COUNT_PERSON ;
		if(a->m_area->m_event_person_count&& pc <= limit_val){
            lock();
			event_tool::instance()->handle_event(OT_AREA,ev,aid,limit_val,pc,a->m_area->m_event_person_count=false,DT_NORMAL);
            unlock();
		    log_info("person_count_leave:%d,v_count:%d limit:%d",aid,pc,limit_val);
        }
		if(a->m_area->m_event_person_show_count&& pc_ <= limit_val){
            lock();
			event_tool::instance()->handle_event(OT_AREA,ev,aid,limit_val,pc_,a->m_area->m_event_person_show_count=false,DT_SPECIAL);
            unlock();
		    log_info("person_count_leave_show:%d,v_count:%d limit:%d",aid,pc,limit_val);
        }
	}
	else if (c->is_vehicle())
	{
        if(ptr)
		    a->m_area->m_vehicle_show_count -- ;
        else{
            a->m_area->m_vehicle_count -- ;
            //if(c->m_display)
            if(flag)
		        a->m_area->m_vehicle_show_count -- ;
        }
        int pc=a->m_area->m_vehicle_count.load();
        int pc_=a->m_area->m_vehicle_show_count.load();
        int limit_val=a->m_area->m_limit_vehicle_count;
        int aid=a->m_area->id();
		EVENT_TYPE ev = a->m_area->is_mine()?EVENT_TYPE::ET_OVER_COUNT_VEHICLE : EVENT_TYPE::ET_AREA_OVER_COUNT_VEHICLE ;
		if(a->m_area->m_event_vehicle_count&& pc <= limit_val){
            lock();
			event_tool::instance()->handle_event(OT_AREA,ev,aid,limit_val,pc,a->m_area->m_event_vehicle_count=false,DT_NORMAL);
            unlock();
		    log_info("vehicle_count_leave:%d,v_count:%d limit:%d",aid,pc,limit_val);
        }
		if(a->m_area->m_event_vehicle_show_count&& pc_ <= limit_val){
            lock();
			event_tool::instance()->handle_event(OT_AREA,ev,aid,limit_val,pc_,a->m_area->m_event_vehicle_show_count=false,DT_SPECIAL);
            unlock();
		    log_info("vehicle_count_leave_show:%d,v_count:%d limit:%d",aid,pc,limit_val);
        }
	}
}