#ifndef __INCLUDE_CARD_MGR__
#define __INCLUDE_CARD_MGR__
#include <memory>
#include <thread>
#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/graph/vector_as_graph.hpp>
#include "tqueue.h"
#include "log.h"
#include "geo_hash.h"

struct card_graph
{
	typedef boost::adjacency_list<boost::vecS,boost::vecS,boost::bidirectionalS> myGraph_vv;
	myGraph_vv m_g;
	uint32_t _count=0;

	void add_edge(uint32_t c1,uint32_t c2)
	{
		log_info("add_edge:%d,%d",c1,c2);
		boost::add_edge(c1,c2,m_g);
		boost::add_edge(c2,c1,m_g);
		_count=boost::num_vertices(m_g);
	}

	void clear_vertex(uint32_t c)
	{
		if(c>=_count) return;
		boost::clear_vertex(c,m_g);
	}
	void remove_edge(uint32_t c1,uint32_t c2)
	{
		if(c1>=_count || c2>=_count) return;
		boost::remove_edge(c1,c2,m_g);
		boost::remove_edge(c2,c1,m_g);
	}
	std::vector<uint32_t> getcard(uint32_t c)
	{
		log_info("--------getcard---------num_edges:%d,%d",boost::num_edges(m_g),_count);
		std::vector<uint32_t> tmp;
		if(c>=_count)return tmp;
		boost::graph_traits<myGraph_vv>::adjacency_iterator ai_it, ai_it_end;
		boost::tie(ai_it, ai_it_end) = boost::adjacent_vertices(c, m_g);
		while(ai_it != ai_it_end)
		{
			log_info("get_card%d:",c);
			log_info("get_card_%d:",*ai_it);
			tmp.push_back(*ai_it);
			ai_it++;
		}
		return std::move(tmp);
	}
};


enum{
	CMD_CLEAR,
	CMD_HANDLE
};
struct Msg
{
	int				cmd;
	int				x;
	int				y;
	uint64_t        cardid;
	int				type;
};

class CardFactory;
struct cardMgr
{
	static cardMgr* instance();
	void run();
	void onMessage(const Msg &m);
	void clear(uint64_t);
	void handleMessage(const Msg &m);
	void erase(const std::map<uint64_t ,std::string>&);
	void erase(uint64_t);
	void tryPut(Msg &m)
	{
		if(!m_queue.tryPut(m))
		  log_error("m_queue tryPut makes error.");
	}
	void addVertex(uint64_t c1,uint64_t c2)
	{
		m_cgraph.add_edge(c1,c2);
	}
	std::vector<uint64_t> getcard(uint64_t cid)
	{
		std::vector<uint64_t> tmpv;
		auto v= m_cgraph.getcard(cid);
		std::for_each(v.begin(),v.end(),[cid,&tmpv](uint32_t cardid){uint64_t id=(cid>>32<<32)|cardid;tmpv.push_back(id);});
		return std::move(tmpv);
	}
	void remove_edge(uint64_t c1, uint64_t c2)
	{
		m_cgraph.remove_edge(c1,c2);
	}
	~cardMgr();
private:
	cardMgr();
	BoundedQueue<Msg>				m_queue;
	bool							m_bstop;
	geo_list						m_glist;
	card_graph						m_cgraph;
	std::unique_ptr<std::thread>	m_pThread;
	std::array<std::shared_ptr<CardFactory>,2> m_cf;
};
#endif

