#ifndef __EVENT_HPP__
#define __EVENT_HPP__
#include <memory>
#include <chrono>
#include<map>
#include<rapidjson/document.h>
#include<rapidjson/writer.h>
#include<rapidjson/stringbuffer.h>
#include<rapidjson/prettywriter.h>

#include<write-copy.h>

enum EVENT_STATUS
{
    ///事件开始
    ES_START = 0,
    ///呼救已处理状态
    ES_DEAL_HELP = 1,
    ///事件结束
    ES_END = 100
};


enum OBJECT_TYPE
{
    ///矿井
    OT_MINE = 1,
    ///区域
    OT_AREA = 2,
    ///分站
    OT_DEVICE_READER = 4,
    ///标识卡，包括人员、车辆、自组网等
    OT_CARD = 9,
};

enum EVENT_TYPE{ // 事件类型
    ET_AREA_OVER_COUNT_PERSON = 3,	// 区域人员超员
    ET_AREA_OVER_COUNT_VEHICLE = 4,	// 区域车辆超员
    ET_READER_ERROR = 6,
    ET_CARD_LOW_POWER_SERIOUS = 12, // 电量极低

    ET_CARD_AREA_OVER_TIME_PERSON = 15, // 人员区域超时
    ET_CARD_AREA_OVER_TIME_VEHICLE = 16, // 车辆区域超时

    ET_CARD_AREA_FORBIDDEN_PERSON = 19,  // 人员进入禁止区域
    ET_CARD_AREA_FORBIDDEN_VEHICLE = 20, // 车辆进入禁止区域
    ET_CARD_OVER_SPEED = 21, // 车辆超速
    ET_CARD_AREA_OVER_SPEED = 22, // 车辆区域超速
    ET_CARD_HELP = 24, // 人员呼救

    ET_CARD_MOTIONLESS=32,//静止不动告警

    ET_VEHICLE_NEAR_GEOFAULT=38,//靠近断层告警
};

struct ya_event
{
private:
    uint64_t m_ev_id;
public:
    ya_event(uint64_t e_id):m_cur_time(std::chrono::system_clock::now())
    {
        m_ev_id = e_id;
        m_obj_id = "";
        m_map_id = 0;
        m_area_id = 0;
        x = 0;
        y = 0;
        m_limit_value = 0;
        m_cur_value = 0;
        m_desc = "";
        m_landmarkid = 0;
        m_landmarkdirect = 0;
        m_landmarkdist = 0;

        m_status=ES_START;
        m_is_display=true;
        m_is_sent=false;
    }
    ~ya_event(){}
public:
    ///告警状态，开始、结束
    EVENT_STATUS m_status;

    ///告警类型
    EVENT_TYPE m_ev_type;
    ///告警对象类型
    OBJECT_TYPE m_obj_type;
    /// 告警对象编号，与告警对象类型对应，如告警对象类型为分站，此字段为分站编号
    std::string m_obj_id;
    ///当前时间，为告警事件的触发时间，如果状态为开始，则表示开始时间，否则为结束时间
    std::chrono::system_clock::time_point m_cur_time;

    ///告警所在地图
    int m_map_id;
    ///告警所在区域
    int m_area_id;
    ///位置
    double x;
    ///位置
    double y;
    ///告警阈值
    double m_limit_value;
    ///当前值
    double m_cur_value;
    ///描述
    std::string m_desc;

    /// 地标信息
    int m_landmarkid;
    /// 与地标的距离
    double m_landmarkdist;
    /// 所处地标的方向
    int m_landmarkdirect;
    //是否显示
    bool m_is_display;
    //是否已经发送 ture bu发送， false推送. 推送完置为true
    bool m_is_sent;

    bool is_end()
    {
        return ES_END == m_status;
    }

    ///作为事件map列表的id，方便查找；
    uint64_t get_list_id();

    uint64_t get_id()
    {
        return m_ev_id;
    }
};

class Event;
struct event_tool
{
    template <class UnaryPredicate>
    void handle_event(OBJECT_TYPE ot,EVENT_TYPE et,uint64_t id,double limit_value,double cur_value,UnaryPredicate p)
    {
        handle_event(ot,et,id,limit_value,cur_value,p());
    }
    void handle_event(OBJECT_TYPE ot,EVENT_TYPE et,uint64_t id,double limit_value,double cur_value,bool f);
    static event_tool * instance();
private:
    event_tool()
    {
        make_event_object();
    }
    void make_event_object();
    std::map<OBJECT_TYPE,std::shared_ptr<Event>>  m_map;
};

struct event_list:single_base<event_list,uint64_t,std::shared_ptr<ya_event>>
{
public:
    static uint64_t to_list_id(EVENT_TYPE ev_type, OBJECT_TYPE obj_type,uint64_t obj_id)
    {
        return (static_cast<uint64_t>(ev_type)<<48)|(static_cast<uint64_t>(obj_type)<<40)|obj_id;
    }

    std::shared_ptr<ya_event> get_event_card(uint32_t card_id, int card_type, EVENT_TYPE ev_type);

    std::shared_ptr<ya_event> get_event_area(int32_t area_id, EVENT_TYPE ev_type)
    {
        return base::get(to_list_id(ev_type, OT_AREA, static_cast<uint64_t>(area_id)));
    }

    std::shared_ptr<ya_event> get_event_reader(int32_t reader_id, EVENT_TYPE ev_type)
    {
        return base::get(to_list_id(ev_type,OT_DEVICE_READER, static_cast<uint64_t>(reader_id)));
    }

    void load_his_data_from_db();

    ~event_list(){}

    static std::string ev_to_json(std::shared_ptr<ya_event> ev_ptr)
    {
        std::vector<std::shared_ptr<ya_event>> evs;
        evs.push_back(ev_ptr);
        return evs_to_json(evs);
    }

    static std::string evs_to_json(std::vector<std::shared_ptr<ya_event>> arr);
private:
    static void _ev_to_node(std::shared_ptr<ya_event> ev_ptr,
                            rapidjson::Document::AllocatorType& allocator,
                            rapidjson::Value& out_data);

};
#endif
