#include "stdafx.h"
#include "carManager.h"
#include "ProcessRemodule.h"
#include "INIFILE.h"
#include "def.h"
#include "YAServerDlg.h"
NAMESPACE_POINT_BEGIN(NAMESPACE_POINT)
//ConfStruct g_cs;

CarManager::CarManager(CYAServerDlg* owner)
	:m_owner(owner)
	,m_bExit(false)
	,m_pThread(NULL)
	,m_queue(256)
	,m_ma(NULL)
	,m_reddis(20)
{
	read_config();
	m_sites.reset(new sit_list());
	m_cf[0] = std::make_shared<CloserCardFactory>();
	m_cf[1] = std::make_shared<RemoteCardFactory>();

	m_dr[0] = std::make_shared<DecoratorRuleCrossing>(this);
	m_dr[1] = std::make_shared<DecoratorRuleAvoidance>(this);
	
	for(const auto & p :m_dr)
		 p->CreateRule();
	m_pThread = new std::thread(&CarManager::run,this);
	m_ma = new MotionlessAlarm(this);
}
CarManager::~CarManager()
{
	m_bExit = true;
	if(m_pThread != NULL)
	{
		m_pThread->join();
		delete m_pThread;
	}
	if(m_ma != NULL)
		delete m_ma;
}

void CarManager::run()
{
	while (!m_bExit)
	{
		std::shared_ptr<TrafficLightGroup> tmp = nullptr;
		if(m_queue.tryGet(tmp))
		{
			m_owner->get_json_all_traffic_lights(tmp);
		}
		//resetTrafficGroup();
		std::this_thread::sleep_for(std::chrono::milliseconds(500));
	}
}
void CarManager::init_sit_list(int32_t readerid,int32_t antid, double ax, double ay,double scale)
{
	m_sites->init_sit_list(readerid,antid,ax,ay,scale);
}
void CarManager::init_sit_list()
{
	m_sites->init_sit_list();
}
void CarManager::init_ant_path(int32_t readerid,int32_t antid, double ax, double ay,std::vector<string>::iterator& b,std::vector<string>::iterator &e)
{
	m_sites->init_ant_path(readerid,antid,ax,ay,b,e);
}
void CarManager::init_ant_path()
{
	m_sites->init_ant_path();
}

void CarManager::init_cardpath()
{
	card_path::init(*m_sites);
}

//-----------set point ---
std::vector<his_location> CarManager::makeUpMorePoints(std::string & cardid,double x,double y, uint64_t ct,int32_t readerid)
{
	std::shared_ptr<base_card> bc = nullptr;
	bc = m_cardList[cardid];
	std::vector<his_location>  vt;
	if (bc)
	{
		vt = bc->make_up_more_points_for_history(point(x,y),ct,&(*m_sites)[readerid]);
	}
	return std::move(vt);
}
//----card----
void CarManager::put(std::string &cardid,const loc_info&li,std::shared_ptr<card_interface> &c,int32_t readerid)
{
	debug_print_syslog(0,"[lemon_smooth_on:%s]t=%lld,sit=%d,ant=%d,card=%d,ct=%d,tof=%d,rav=%d,acc=%d,rsp=%.1f,cardType:%d\n"
		,cardid.c_str(),li.m_loc_time,readerid, li.m_ant_id, li.m_card_id ,li.m_card_ct,li.m_tof
		,li.m_rav,li.m_acc,li.m_card_sp,li.m_card_type );
	std::shared_ptr<base_card> bc = nullptr;
	bc = m_cardList[cardid];
	if (!bc)
	{
		bc = std::make_shared<base_card>(c,li.m_card_id);
		m_cardList.insert(cardid,bc);
	}
	bc->on_tof_data(&(*m_sites)[readerid],li);
}

void CarManager::erase(std::string cardid)
{
	std::stringstream ss;
	std::shared_ptr<base_card> bc = nullptr;
	bc = m_cardList[cardid];

	if (bc != nullptr)
	{
		ss<<"LemonHash Erase.."<<cardid;

		for(auto s:bc->m_card->m_v)
		{
			ss<<" "<<s;
		}
		debug_print_syslog(0,"%s",ss.str().c_str());
		std::vector<std::string> tmp(bc->m_card->m_v.begin(),bc->m_card->m_v.end());
		for(int i = m_cf.size()-1;i>=0;i--)
		{
			//升井的时候，对由于时长未到，而未进行以人多卡检测的数据进行最后的check。
			auto mp = m_cf[i]->erase(bc->m_card,m_cardList,tmp);
			if(i == 0 && !mp.empty())
			{
				m_owner->uwb_alarm(mp,i,bc->m_card);
			}
		}
		m_cardList.erase(cardid);
		bc->m_card->m_v.clear();
		bc->m_card->m_m.clear();
	}
}
loc_point CarManager::getpoint(std::string cardid)
{
	std::shared_ptr<base_card> bc = nullptr;
	bc = m_cardList[cardid];
	if (bc)
	{
		return std::move(bc->grab_loc_point());
	}
	else
	{
		return std::move(loc_point());
	}
}

/*
 * 
 *
 * 参数
 *		c		卡对象
 *
 * 返回值
 *		无
 *
*/
void CarManager::uwb_HandleMoreCard(std::shared_ptr<card_interface>& c)
{
	//debug_print_syslog(0,"[ConfStruct:%s]",ConfStruct::getCs().to_str().c_str());
	//获得卡的坐标信息(x,y)，卡号，卡的接收时间
	int x = c->getX();
	int y = c->getY();
	std::string cardid = c->cardId();
	uint64_t ctime =  c->CtTime();

	std::stringstream ss;
	
	//查找距离此卡号为cardid附近MaxScope范围内的所有卡，将这些卡号保存到rc中
	std::vector<std::string> rc=m_g.find_near(cardid,ConfStruct::getCs().MaxScope);

	//删除rc内所有不是人卡的数据
	rc.erase(std::remove_if(rc.begin(),rc.end(),[](const std::string &name){
		if(0 == name.compare(0,3,"001"))
			return false;
		else
			return true;}),rc.end());
	//输出rc的大小，卡号，接收时间，卡的坐标（x,y）
	//ss<<"LemonHash["<<rc.size()<<"]"<<c->cardId()<<" "<<ctime<<" x:"<<x<<" y:"<<y;
	//debug_print_syslog(0,"%s",ss.str().c_str());

	//计算并输出卡号cardid附近的rc内所有卡距离此卡cardid的接收时间差,以及这些卡的
	//std::for_each(rc.begin(),rc.end(),[&](const std::string &s)
	//	{
	//		std::stringstream ss;
	//		std::shared_ptr<base_card> bc = nullptr;
	//		bc = m_cardList[s];

	//		if (bc!=nullptr)
	//		{
	//			std::shared_ptr<card_interface>&xc = bc->m_card;
	//			int ctd = xc->CtTime()>ctime ?(xc->CtTime()-ctime):(ctime-xc->CtTime());
	//			ss<<"-----LemonHash----"<<s<<" ct:"<<xc->CtTime()<<" Vct:"<<ctd<<" x:"<<xc->getX()<<" y:"<<xc->getY()<<" dis:"<<(sqrt(pow(x-xc->getX(),2)+pow(y-xc->getY(),2)));
	//			debug_print_syslog(0,"%s",ss.str().c_str());
	//		}
	//	}
	//);
	//
	std::map<uint64_t,std::string> map1;
	std::map<uint64_t,std::string> map2;
	for(int i = m_cf.size()-1;i>=0;i--)
	{
		map1.clear();
		map2.clear();
		map1=m_cf[i]->selectcard(rc.begin(),rc.end(),c,m_cardList);
		map2=m_cf[i]->setCT(c);
		std::copy(map1.begin(),map1.end(),std::inserter(map2,map2.end()));

		if (i == 1 && !map2.empty())
		{
			//for (auto it:map2)
			//{
			//	debug_print_syslog(0,"---++LemonHash CatchOne Remote--%lld-%s",it.first,it.second.c_str());
			//}
			erase(map2);
		}

		if (!map2.empty())
		{
			//for (auto it:map2)
			//{
			//	debug_print_syslog(0,"---++LemonHash CatchOne--%lld-%s",it.first,it.second.c_str());
			//}
			//
			m_owner->uwb_alarm(map2,i,c);
		}

		//if (!rc.empty())
		//{
		//	std::string s ;
		//	s = m_cf[i]->infomessage();
		//	debug_print_syslog(0,"---lemonhash----[%s]%s",i?"remote":"closer",s.c_str());
		//}
	}
}
void CarManager::erase(std::map<uint64_t,std::string> &m) 
{
	for(const auto s:m)
		for(const auto x:m_cf)
			x->erase(s.first,m_cardList);
}
void CarManager::read_config()
{
	IniFile ini;
	if(ini.open(FILEPATH_SERVER_CONFIG)){
		ConfStruct::getCs().TimeAlarm_Remote = atof(ini.read(CONF_SECT_SERVER_SETTING,"TimeAlarm_Remote").c_str());
		ConfStruct::getCs().TimeAlarm_Closer = atof(ini.read(CONF_SECT_SERVER_SETTING,"TimeAlarm_Closer").c_str());
		ConfStruct::getCs().TimeWin = atoi(ini.read(CONF_SECT_SERVER_SETTING,"TimeWin").c_str());
		ConfStruct::getCs().MaxScope = atoi(ini.read(CONF_SECT_SERVER_SETTING,"MaxScope").c_str());
		ConfStruct::getCs().limit_sec= atoi(ini.read(CONF_SECT_SERVER_SETTING,"LimitSec").c_str());
		ConfStruct::getCs().max_scope_bigCar = atof(ini.read(CONF_SECT_SERVER_SETTING,"MaxScopeBigCar").c_str());
		ConfStruct::getCs().mid_car_length_goroup= atof(ini.read(CONF_SECT_SERVER_SETTING,"midCarLengthGroup").c_str());
		ConfStruct::getCs().check_count = atoi(ini.read(CONF_SECT_SERVER_SETTING,"CheckCount").c_str());
		ConfStruct::getCs().response_alarm_time  = atoi(ini.read(CONF_SECT_SERVER_SETTING,"ResponseAlarmTime").c_str());
		m_reddis = atof(ini.read(CONF_TRAFFIC_LIGHT,CONF_RED_DISTANCE).c_str());
	}
	ConfStruct::getCs().closer_slot = (int)(ConfStruct::getCs().TimeAlarm_Closer*60/ConfStruct::getCs().TimeWin + 1);
	ConfStruct::getCs().remote_slot = (int)(ConfStruct::getCs().TimeAlarm_Remote*60/ConfStruct::getCs().TimeWin + 1);
	ConfStruct::getCs().split_win_minsec = ConfStruct::getCs().TimeWin*60*1000;
}
void CarManager::initRule()
{
	for(auto x:m_Map)
		for(auto &pT:m_dr)
			pT->put(x.second);
	for(auto & pT:m_dr)
	{
		pT->handleRule();
		//debug_print_syslog(0,"initRule:%s",pT->showInfo().c_str());
	}
}
void CarManager::showInfo()
{
	for(const auto x : m_Map)
		debug_print_syslog(0,"TrafficGroup:%s",x.second->showinfo().c_str());
}
void CarManager::put(std::shared_ptr<TrafficLightGroup> t,int gid)
{
	m_Map.insert(std::make_pair(gid,t));
}
void CarManager::handleRule(std::shared_ptr<card_interface> c)
{
	m_dr[1]->handleRule(c);
}

bool CarManager::resetTrafficGroup()
{
	for(auto it_group : m_Map){
		/*if(!it_group.second->get_status()){
			continue;
		}*/
		if(it_group.second->m_sCardId.empty())
		{
			continue;
		}
		std::string card_id = "";
		card_id = it_group.second->m_sCardId;
		auto card_ptr = m_dr[1]->getCard(card_id);
		if(!card_ptr){
			//debug_print_syslog(0,"lamp light : resetTrafficGroup card_id: %s, gid: %d",card_id.c_str(),it_group.second->m_gId);
			continue;
		}
		std::time_t t = time(NULL);
		//debug_print_syslog(0,"lamp light : status: %d ,now: %llu, last: %llu,",it_group.second->get_status(),t,card_ptr->get_last_recv_time());
		
		if(t-card_ptr->get_last_recv_time()>= 10)
		{
			debug_print_syslog(0,"lamp light : resetTrafficGroup card_id: %s,gid: %d status: %d ,now: %llu, last: %llu,",card_id.c_str(),it_group.second->m_gId,it_group.second->get_status(),t,card_ptr->get_last_recv_time());
			it_group.second->resetGroup();
			it_group.second->releaseTurn();
			std::vector<std::shared_ptr<TrafficLightGroup>> vt;
			vt.push_back(it_group.second);
			getSendLightInfo(std::move(vt));
		}
	}
	return true;
}

std::shared_ptr<RunRedLight> CarManager::check_run_red_light(std::shared_ptr<card_interface> c)
{
	return m_dr[1]->check_run_red_light(c,m_reddis);
}

void CarManager::setManual(int gid,int lid,std::string name,int state)
{
	std::vector<std::shared_ptr<TrafficLightGroup>> vt;

	if(auto p = m_Map[gid])
	{
		p->setManualControl(name,lid,(op::LIGHT_COLOUR)state);
		vt.push_back(p);
		getSendLightInfo(std::move(vt));
	}
}
void CarManager::cancelManual(int gid)
{
	std::vector<std::shared_ptr<TrafficLightGroup>> vt;
	if(auto p = m_Map[gid])
	{
		p->getTurn();
		p->resetGroup();
		p->releaseTurn();
		vt.push_back(p);
		getSendLightInfo(std::move(vt));
	}
}
void CarManager::getSendLightInfo(std::vector<std::shared_ptr<TrafficLightGroup>> && p,std::string s)
{
	for (const auto x : p)
	{
		debug_print_syslog(0,"[getSendLight]%s,%s",s.c_str(),x->showinfo().c_str());
		m_queue.tryPut(x);
	}
}
void CarManager::push_back(std::shared_ptr<card_interface> &ci)
{
	m_ma->pushback(ci);
}

int NAMESPACE_POINT::CarManager::getTrafficGroupId(const uint32_t& light_id)
{
	bool bFind = false;
	int group_id = -1;
	for (auto it_group : m_Map)
	{
		for (auto it_light : it_group.second->m_pTrafficLight)
		{
			if (it_light->m_physics_light_id == light_id)
			{
				bFind = true;
				break;
			}
		}
		if (bFind)
		{
			group_id = it_group.first;
		}
	}

	return group_id;
}

/*
 * 根据物理灯号获得所对应的所有红绿灯编号
 *
 * param
 *		phy_light_id		物理灯号
 *
 * return
 *		指定物理灯号对应的所有红绿灯编号
 *
*/
std::vector<uint32_t> NAMESPACE_POINT::CarManager::getPhysicsTrafficLightId(const uint32_t& phy_light_id)
{
	std::vector<uint32_t> ret;
	ret.resize(0);

	for (auto it_group : m_Map)
	{
		for (auto it_light : it_group.second->m_pTrafficLight)
		{
			if (it_light->m_physics_light_id == phy_light_id)
			{
				ret.push_back(it_light->getid());
			}
		}
	}

	return std::move(ret);
}

/*
 * 获得红绿灯对象
 *
 * param
 *		light_id		红绿灯id
 *
 * return
 *		红绿灯对象
 *
*/
std::shared_ptr<NAMESPACE_POINT::TrafficLight> NAMESPACE_POINT::CarManager::getTrafficLight(const uint32_t& light_id)
{
	std::shared_ptr<NAMESPACE_POINT::TrafficLight> pTrafficLight = nullptr;
	for (auto it : m_Map)
	{
		if(nullptr != it.second->get(light_id)){
			pTrafficLight = it.second->get(light_id);
		}
	}
	return pTrafficLight;
}

void CarManager::determineCard(std::shared_ptr<card_interface> & ci)
{
	m_ma->determine(ci);
}
void CarManager::deal_alarm_card(std::shared_ptr<card_interface> & ci,bool flag)
{
	m_owner->deal_alarm_card_motionless(ci,flag);
}
void CarManager::erase(std::shared_ptr<card_interface> &ci)
{
	m_ma->erase(ci);
}

MotionlessAlarm::MotionlessAlarm(CarManager *cm)
	:m_owner(cm)
	,m_bExit(false)
	,m_pTh(NULL)
{
	m_pTh = new std::thread(&MotionlessAlarm::run,this);
}
MotionlessAlarm::~MotionlessAlarm()
{
	m_bExit = true;

	if (m_pTh != NULL)
	{
		m_pTh->join();
		delete m_pTh;
	}

}
void MotionlessAlarm::run()
{
	while (!m_bExit)
	{
		std::this_thread::sleep_for(std::chrono::milliseconds(500));
		std::lock_guard<std::mutex> lck(m_mtx);
		for(auto &c :m_cardlist)
		{
			uint64_t t = time(NULL)*1000;
			uint64_t tt = c->CtTime();
			uint64_t ttt=t>tt?t-tt:tt-t;
			if (ttt > ConfStruct::getCs().response_alarm_time*1000 && isMotionless(c))
			{
				if (!c->_isMotionless)
				{
					debug_print_syslog(0,"[motionless]Alarm True:%s,%lld,%lld,%lld,%d,%s",c->cardId().c_str(),t,tt,ttt,c->getCount(),c->_isMotionless?"true":"false");
					//alarm
					m_owner->deal_alarm_card(c,true);
				}
			}
			else
			{
				if (c->_isMotionless)
				{
					debug_print_syslog(0,"[motionless]Alarm False:%s,%lld,%lld,%lld,%d,%s",c->cardId().c_str(),t,tt,ttt,c->getCount(),c->_isMotionless?"true":"false");
					//cancel alarm
					m_owner->deal_alarm_card(c,false);
				}
			}
		}
	}
}
bool MotionlessAlarm::find(std::shared_ptr<card_interface> &ci)
{
	if(std::find(m_cardlist.begin(),m_cardlist.end(),ci) != std::end(m_cardlist))
		return true;
	else
		return false;
}
void MotionlessAlarm::determine(std::shared_ptr<card_interface> &ci)
{
	//add index.
	ci->motionlessFlag();
	//
	if (isMotionless(ci))
	{
		if(!find(ci))
		{
			debug_print_syslog(0,"[motionless]cardId:%s,%d",ci->cardId().c_str(),ci->getCount());
			std::lock_guard<std::mutex> lck(m_mtx);
			m_cardlist.push_back(ci);
		}
	}
}
bool MotionlessAlarm::isMotionless(std::shared_ptr<card_interface> &ci)
{
	if(ci->getCount() > ConfStruct::getCs().check_count)
		return true;
	else
		return false;
}
void MotionlessAlarm::erase(std::shared_ptr<card_interface> &ci)
{
	if (find(ci))
	{
		debug_print_syslog(0,"[motionless]erase:%s",ci->cardId().c_str());
		std::lock_guard<std::mutex> lck(m_mtx);
		m_cardlist.remove(ci);
	}
}
void MotionlessAlarm::pushback(std::shared_ptr<card_interface> &ci)
{
	m_cardlist.push_back(ci);
}
NAMESPACE_POINT_END(NAMESPACE_POINT)