/**************************************************************************************************
 * File Name	: StudentMgr.cpp
 * Created		: 08/09/15
 * Author		: ChenWei
 * Model			: TSD
 * Description	: Student Manager.
 **************************************************************************************************/
#include "StudentMgr.h"
#include "RegMgr.h"
#include "Student.h"
#include "libsesdata.h"
#include "OperationManager.h"
#include "NetSSLClientWrapper.h"
#include <iterator>
#include <list>
#include <string>
#include <zlib.h>
using namespace LibSESData;
using namespace std;

/**************************************************************************************************
 * Function Name	: CStudentMgr
 * Description		: Construct CStudentMgr construct
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
CStudentMgr::CStudentMgr()
{
	CSESLog::WriteLine("CStudentMgr::CStudentMgr()>>Start");
	m_pCOperationManager = NULL;
	bStart = true;
	m_StudentVector.clear();
	//SetParameter();
	mp_TP_Reactor = NULL;
	mp_Reactor = NULL;
	bFirst = 1;
	ACE_OS::thread_mutex_init(&mc_mgr_lock);
	conn = NULL;
	//conn = new CNetSSLClientWrapper();
	CSESLog::WriteLine("CStudentMgr::CStudentMgr()<<End");
}

/**************************************************************************************************
 * Function Name	: ~CStudentMgr
 * Description		: Destroy CStudentMgr
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
CStudentMgr::~CStudentMgr()
{
	CSESLog::WriteLine("CStudentMgr::~CStudentMgr()<<Start");
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);

	int size = m_StudentVector.size();
	for (int i = 0; i < size; i++)
	{
		RemoveHandle(m_StudentVector[i]);
		delete m_StudentVector[i];
	}
	m_StudentVector.clear();
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	if (NULL != mp_Reactor)
	{
		delete mp_Reactor;
		mp_Reactor = NULL;
	}
	if (NULL != mp_TP_Reactor)
	{
		delete mp_TP_Reactor;
		mp_TP_Reactor = NULL;
	}
	//m_pCOperationManager = NULL;
	CSESLog::WriteLine("CStudentMgr::~CStudentMgr()<<End");
}

/**************************************************************************************************
 * Function Name	: instance
 * Description		: Get CStudentMgr's singleton.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
CStudentMgr* CStudentMgr::instance()
{
	return ACE_Singleton<CStudentMgr, ACE_SYNCH_MUTEX>::instance();
}

/**************************************************************************************************
 * Function Name	: Open
 * Description		: Open the Recv thread.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::Open()
{
	CSESLog::WriteLine("CStudentMgr::Open()<<Start");
	int iResult = 0;
	bool bReturn = true;
	do
	{
		if (SSL_CTX_use_certificate_file(
				ACE_SSL_Context::instance()->context(), CERTIFICATE,
				X509_FILETYPE_PEM) <= 0)
		{
			CSESLog::WriteLine("Verifycertificate", CSESLog::ERROR);
			CSESLog::WriteLine(ACE_OS_String::strerror(errno), CSESLog::WARNING);
		}
		//		SSL_CTX_set_default_passwd_cb_userdata(m_pContext->context(),(void*) m_Password.c_str());
		ACE_SSL_Context::instance()->context()->default_passwd_callback_userdata
				= (void*) RegMgr::instance()->GetPassword().c_str();
		ifstream inFile;
		inFile.open(PRIVATE_KEY);
		if (inFile.fail())
		{
			bReturn = false;
			break;
		}
		inFile.close();
		if (SSL_CTX_use_PrivateKey_file(ACE_SSL_Context::instance()->context(),
				PRIVATE_KEY, X509_FILETYPE_PEM) <= 0)
		{
			CSESLog::WriteLine("context->private_key", CSESLog::ERROR);
			CSESLog::WriteLine(ACE_OS_String::strerror(errno), CSESLog::WARNING);
			bReturn = false;
			break;

		}
		if (0 != ACE_SSL_Context::instance()->verify_private_key())
		{
			CSESLog::WriteLine(-1,
					"COperationManager::verify_private_key>>Err:",
					CSESLog::ERROR);
			CSESLog::WriteLine(errno, ACE_OS_String::strerror(errno));
			bReturn = false;
			break;
		}

		bFirst = 0;

		if (NULL == mp_TP_Reactor)
		{
			mp_TP_Reactor = new ACE_TP_Reactor();
		}
		if (NULL == mp_Reactor)
		{
			mp_Reactor = new ACE_Reactor(mp_TP_Reactor);
		}

		bStart = true;

		ACE_Reactor::instance(mp_Reactor);
		if ((iResult = ACE_Reactor::instance()->open(MAX_NUMBER_OF_HANDLES))
				< 0)
		{
			CSESLog::WriteLine(iResult, "	ACE_Reactor::instance()->open:");
		}
		if ((iResult = ACE_Reactor::instance()->initialized()) <= 0)
		{
			CSESLog::WriteLine(iResult, "ACE_Reactor::instance()->initialized:");
		}
		if (NULL != conn)
		{
			delete conn;
			conn = NULL;
		}
		conn = new CNetSSLClientWrapper();
		ACE_Reactor::instance()->schedule_timer(this, 0, ACE_Time_Value(
				STUDENT_HEARTTIMER));
		ACE_OS::thread_mutex_lock(&mc_mgr_lock);
		int max = m_StudentVector.size();

		//	ACE_Reactor::instance()->initialized();
		//	int iOpen = ACE_Reactor::instance()->open(MAX_NUMBER_OF_HANDLES);
		//	CSESLog::WriteLine(iOpen, "ACE_Reactor::instance()->open");
		for (int var = 0; var < max; ++var)
		{
			delete m_StudentVector[var];
		}
		m_StudentVector.clear();
		ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
		ACE_Thread_Manager::instance()->spawn_n(10,
				(ACE_THR_FUNC) RegMgr::RegMgrThread, 0, THR_NEW_LWP, //New Light Weight Process
				ACE_DEFAULT_THREAD_PRIORITY// ACE_THR_PRI_RR_MAX
				, REGMGR_THREAD_GRP);
	} while (0);
	return bReturn;
}

/**************************************************************************************************
 * Function Name	: StuMgrThread
 * Description		: StuMgrThread.
 * Date				: 08/09/15
 * Parameter		: void *arg
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void* CStudentMgr::StuMgrThread(void *arg)
{
	CStudentMgr::instance()->StuMgrOpen();
	return NULL;
}

/**************************************************************************************************
 * Function Name	: StuMgrOpen
 * Description		: Open the Recv thread.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::StuMgrOpen()
{
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	int max = m_StudentVector.size();

	//	ACE_Reactor::instance()->initialized();
	//	int iOpen = ACE_Reactor::instance()->open(MAX_NUMBER_OF_HANDLES);
	//	CSESLog::WriteLine(iOpen, "ACE_Reactor::instance()->open");
	for (int var = 0; var < max; ++var)
	{
		AddHandle(m_StudentVector[var]);
	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	int i = 0;
	while (bStart)
	{

		i = ACE_Reactor::instance()->handle_events();
	}
	return;
}

/**************************************************************************************************
 * Function Name	: Close
 * Description		: Close the Recv thread.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::Close()
{
	CSESLog::WriteLine(" CStudentMgr::Close()>>Start");
	bStart = false;
	int iResult = 0;
	if (NULL != conn)
	{
		ACE_Reactor::instance()->cancel_timer(this, 1);
		ACE_OS::thread_mutex_lock(&mc_mgr_lock);

		int size = m_StudentVector.size();
		for (int i = 0; i < size; i++)
		{
			RemoveHandle(m_StudentVector[i]);

			//delete m_StudentVector[i];
			m_StudentVector[i]->Close();
			m_StudentVector[i]->Schedule_timer();
		}
		m_StudentVector.clear();
		ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
		iResult = ACE_Reactor::instance()->end_event_loop();//_reactor
		if (1 > iResult)
		{

			CSESLog::WriteLine(iResult,
					" ACE_Reactor::instance()->end_reactor_event_loop():", 0,
					CSESLog::ERROR);

		}
		iResult = ACE_Reactor::instance()->event_loop_done();//reactor_
		if (1 > iResult)
		{

			CSESLog::WriteLine(iResult,
					" ACE_Reactor::instance()->reactor_event_loop_done():", 0,
					CSESLog::ERROR);
		}
		//ACE_Reactor::instance()->reset_reactor_event_loop();
		if (NULL != conn)
		{
			delete conn;
			conn = NULL;
		}
		//m_pCOperationManager = NULL;
		//ACE_Reactor::instance()->close();
		//	if (-1 == ACE_Thread_Manager::instance()->wait_grp(STUDENTMGR_THREAD_GRP))
		//	{
		//		// add kill
		//		ACE_Thread_Manager::instance()->cancel_grp(STUDENTMGR_THREAD_GRP);
		//	}
		//	if ((iResult = ACE_Reactor::instance()->close()) < 1)
		//	{
		//		CSESLog::WriteLine(iResult, "ACE_Reactor::instance()->close():");
		//
		//	}
		//ACE_Reactor::instance()->close_singleton();

		CSESLog::WriteLine(
				"ACE_Thread_Manager::instance()->wait_grp(REGMGR_THREAD_GRP):start");
		bool bReturn = true;
		if (-1 == ACE_Thread_Manager::instance()->wait_grp(REGMGR_THREAD_GRP))
		{
			CSESLog::WriteLine(
					"ACE_Thread_Manager::instance()->wait_grp(REGMGR_THREAD_GRP):-1");
			bReturn = false;
			ACE_Thread_Manager::instance()->cancel_grp(REGMGR_THREAD_GRP);
		}
		ACE_Thread_Manager::instance()->cancel_grp(REGMGR_THREAD_GRP);

		if ((iResult = ACE_Thread_Manager::instance()->close()) < 1)
		{
			CSESLog::WriteLine(iResult,
					"ACE_Thread_Manager::instance()->close():");

		}
		if (NULL != mp_Reactor)
		{
			delete mp_Reactor;
			mp_Reactor = NULL;
		}
		if (NULL != mp_TP_Reactor)
		{
			delete mp_TP_Reactor;
			mp_TP_Reactor = NULL;
		}
	}
	//ACE_Thread_Manager::instance()->close();
	CSESLog::WriteLine(" CStudentMgr::Close()<<End");
}

/**************************************************************************************************
 * Function Name	: RegisterCOperationManager
 * Description		: Register COperationManager
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::RegisterCOperationManager(
		COperationManager *cOperationManager)
{
	m_pCOperationManager = cOperationManager;
}

/**************************************************************************************************
 * Function Name	: AddNewStudent
 * Description		: AddNewStudent :for REGMGR to addStudent
 * Date				: 08/09/15
 * Parameter		: Student* student
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::AddNewStudent(Student* student)
{

	bool bReturn = true;
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	std::vector<Student*>::iterator startIterator;
	std::string studentId;
	student->GetStudentID(studentId);
	std::string existStudentID;
	startIterator = m_StudentVector.begin();

	int size = m_StudentVector.size();
	for (int i = 0; i < size; i++)
	{

		((Student*) m_StudentVector[i])-> GetStudentID(existStudentID);

		if ((existStudentID.compare(studentId) == 0))
		{

			//			RemoveHandle(m_StudentVector[i]);
			//
			//			delete m_StudentVector[i];
			//
			//			m_StudentVector[i] = student;

			bReturn = false;
			break;
		}
		startIterator++;

	}
	if (bReturn)
	{
		//high move to reactor!!!!
		m_StudentVector.push_back(student);
		bReturn = true;
		AddHandle(student);;

	}
	else
	{
		CSESLog::WriteLine(CSESLogData::LOG_STUDENT_CONNECTTEACHER,
				"CStudentMgr::AddNewStudent send msg to network", "%s",
				METHOD_REPEATSTUDENTID);
		std::string msg;
		CIntfData myData;
		myData.SetMessage(TEACHER_CONTROLNEWSTUDENTCONNECT);
		myData.SetStudentID(studentId);
		myData.ParaXmlDoc.setString("allow", METHOD_REPEATSTUDENTID);
		myData.toString(msg);

		unsigned long iLen = 0;
		unsigned char* pucStr = NULL;

		if (CSESDataTools::Compress(msg, &pucStr, iLen))
		{
			student->Send(pucStr, iLen);
			delete pucStr;
		}

		CSESLog::WriteLine(CSESLogData::LOG_STUDENT_CONNECTTEACHER,
				"COperationManager::Work TEACHER_CONTROLNEWSTUDENTCONNECT Get msg from DBus ");

		delete student;
	}

	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);

	return bReturn;

}

/**************************************************************************************************
 * Function Name	: Clear
 * Description		: Clear the m_StudentVector.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::Clear()
{
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);

	int size = m_StudentVector.size();
	for (int i = 0; i < size; i++)
	{
		RemoveHandle(m_StudentVector[i]);
		delete m_StudentVector[i];
	}

	m_StudentVector.clear();
	//ACE_Reactor::instance()->close();
	//ACE_Reactor::instance()->open((size_t) MAX_NUMBER_OF_HANDLES);
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
}

/**************************************************************************************************
 * Function Name	: SetParameter
 * Description		: Set SSL Parameter.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::SetParameter()
{
	//	ACE_SSL_Context *context = ACE_SSL_Context::instance();
	//
	//	CSESLog::WriteLine(ACE_OS_String::strerror(errno));
	//	if (context->certificate(CERTIFICATE, SSL_FILETYPE_PEM) < 0)
	//	{
	//		CSESLog::WriteLine("CStudentMgr::SetParameter>>Err", CSESLog::ERROR);
	//	}
	//	CSESLog::WriteLine(ACE_OS_String::strerror(errno));
	//	if (context->private_key(PRIVATE_KEY, SSL_FILETYPE_PEM) < 0)
	//	{
	//		CSESLog::WriteLine("CStudentMgr::SetParameter>>Err", CSESLog::ERROR);
	//	}
	//	if (0 != context->verify_private_key())
	//	{
	//		CSESLog::WriteLine("RegMgr::verify_private_key>>Err", CSESLog::ERROR);
	//		CSESLog::WriteLine(context->verify_private_key(),
	//				ACE_OS_String::strerror(errno));
	//	}
	//	CSESLog::WriteLine(context->verify_private_key(), ACE_OS_String::strerror(
	//			errno));
}

/**************************************************************************************************
 * Function Name	: GetStudentIDVector
 * Description		:
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::GetStudentIDVector(std::vector<std::string>& vector)
{
	bool bReturn = 1;
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	string ID;
	int size = m_StudentVector.size();
	for (int i = 0; i < size; i++)
	{
		m_StudentVector[i]->GetStudentID(ID);
		vector.push_back(ID);
	}

	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	return bReturn;
}

/**************************************************************************************************
 * Function Name	: DelStudent
 * Description		: Delete Student from m_StudentVector.
 * Date				: 08/09/15
 * Parameter		: const CIntfData& intfData
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::DelStudent(const CIntfData& intfData)
{
	std::string studentId;
	std::string existStudentId;
	intfData.GetStudentID(studentId);
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	std::vector<Student*>::iterator startIterator = m_StudentVector.begin();
	std::vector<Student*>::iterator endIterator = m_StudentVector.end();

	for (startIterator = m_StudentVector.begin(); startIterator != endIterator; startIterator++)
	{
		(*startIterator)->GetStudentID(existStudentId);

		if (existStudentId == studentId)
		{
			RemoveHandle(*startIterator);
			delete *startIterator;
			m_StudentVector.erase(startIterator);
			break;
		}

	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	return;
}

/**************************************************************************************************
 * Function Name	: DelStudent
 * Description		: Delete Student from m_StudentVector.
 * Date				: 08/09/15
 * Parameter		: const std::string& studentID
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::DelStudent(const std::string& studentID)
{
	CSESLog::WriteLine("CStudentMgr::DelStudent start:");
	CSESLog::WriteLine(studentID);
	std::vector<Student*>::iterator startIterator;

	std::string existStudentID;
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	startIterator = m_StudentVector.begin();
	bool bReturn = false;
	int size = m_StudentVector.size();
	for (int i = 0; i < size; i++)
	{

		((Student*) m_StudentVector[i])-> GetStudentID(existStudentID);

		if (existStudentID.compare(studentID) == 0)
		{
			RemoveHandle(*startIterator);

			delete *startIterator;
			m_StudentVector.erase(startIterator);
			bReturn = true;
			break;
		}
		startIterator++;
	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	CSESLog::WriteLine("CStudentMgr::DelStudent ed");
	return;
}

/**************************************************************************************************
 * Function Name	: WillDelStudent
 * Description		: Delete Student from m_StudentVector.
 * Date				: 08/09/15
 * Parameter		: const std::string& studentID
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::WillDelStudent(const std::string& studentID)
{
	CSESLog::WriteLine("CStudentMgr::DelStudent start:");
	CSESLog::WriteLine(studentID);
	std::vector<Student*>::iterator startIterator;

	std::string existStudentID;
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	startIterator = m_StudentVector.begin();
	bool bReturn = false;
	int size = m_StudentVector.size();
	for (int i = 0; i < size; i++)
	{

		((Student*) m_StudentVector[i])-> GetStudentID(existStudentID);

		if (existStudentID.compare(studentID) == 0)
		{
			RemoveHandle(*startIterator);

			//delete *startIterator;
			(*startIterator)->Close();
			(*startIterator)->Schedule_timer();
			m_StudentVector.erase(startIterator);
			bReturn = true;
			break;
		}
		startIterator++;
	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	CSESLog::WriteLine("CStudentMgr::DelStudent ed");
	return;
}

/**************************************************************************************************
 * Function Name	: handle_timeout
 * Description		: handle_timeout.
 * Date				: 08/09/15
 * Parameter		: const ACE_Time_Value &tv, const void *arg
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
int CStudentMgr::handle_timeout(const ACE_Time_Value &tv, const void *arg)
{
	// beta HeartBeat
	CSESLog::WriteLine("CStudentMgr::handle_timeout start");
	CIntfData cIntfData;
	cIntfData.SetMessage(TEACHER_NOTIFYSTUDENTSTATUSCHANGED);

	cIntfData.ParaXmlDoc.setInt("iStatus", STUDENT_TIMEOUT_MESSAGE);

	std::vector<Student*>::iterator startIterator;
	std::vector<Student*>::iterator endIterator;
	time(&m_TimerNew);

	ACE_OS::thread_mutex_lock(&mc_mgr_lock);

	endIterator = m_StudentVector.end();
	string stuID;
	unsigned long iLen = 0;
	unsigned char* pucStr = NULL;
	string msg(HEARTBEATMESSAGE);
	CSESDataTools::Compress(msg, &pucStr, iLen);
	vector<string> stuIDVector;
	for (startIterator = m_StudentVector.begin(); startIterator != endIterator; startIterator++)
	{
		if ((*startIterator)->Timeout(m_TimerNew))
		{

			(*startIterator)->GetStudentID(stuID);
			CSESLog::WriteLine("CStudentMgr::handle_timeout del student:");
			CSESLog::WriteLine(stuID);
			stuIDVector.push_back(stuID);
			(*startIterator)->Close();
			(*startIterator)->Schedule_timer();
			//delete (*startIterator);


			m_StudentVector.erase(startIterator);
			//m_StudentVector.erase
		}
		else
		{
			(*startIterator)->Send(pucStr, iLen);
		}
		//		if (!iStartTime)
		//		{
		//			COperationManagerCallBack(cIntfData);
		//			startIterator->close();
		//			m_StudentVector.erase(startIterator);
		//		}
	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	int stuIDVectorSize = stuIDVector.size();
	for (int j = 0; j < stuIDVectorSize; j++)
	{

		COperationManagerDisconnectCallBack(stuIDVector[j]);
	}

	delete pucStr;
	//CStudentMgr::instance()->COperationManagerCallBack(cIntfData);

	ACE_Reactor::instance()->schedule_timer(this, 0, ACE_Time_Value(
			STUDENT_HEARTTIMER));
	CSESLog::WriteLine("CStudentMgr::handle_timeout end");
	return 0;
}
/**************************************************************************************************
 * Function Name	: get_handle
 * Description		: get_handle
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
ACE_HANDLE CStudentMgr::get_handle(void) const
{
	return conn->GetHandle();

}
/**************************************************************************************************
 * Function Name	: AddHandle
 * Description		: AddHandle for reator..
 * Date				: 08/09/15
 * Parameter		: Student* student
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::AddHandle(Student* student)
{

	ACE_Reactor::instance()->register_handler(student,
			ACE_Event_Handler::READ_MASK);
	//	ACE_Reactor::instance()->register_handler(student,
	//				ACE_Event_Handler::WRITE_MASK);
	//	ACE_Reactor::instance()->remove_handler(student,
	//					ACE_Event_Handler::WRITE_MASK);
	//	ACE_Reactor::instance()->schedule_timer(student, 0, ACE_Time_Value(
	//			STUDENT_TIMEOUT));
}

/**************************************************************************************************
 * Function Name	: RemoveHandle
 * Description		: Remove Handle from the ACE_Reactor::instance().
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::RemoveHandle(Student* student)
{
	ACE_Reactor::instance()->remove_handler(student,
			ACE_Event_Handler::READ_MASK);

	//ACE_Reactor::instance()->cancel_timer(student, 0);
}

/**************************************************************************************************
 * Function Name	: RemoveHandle
 * Description		: Remove Handle from the ACE_Reactor::instance().
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::RemoveHandle(const string& studentId)
{
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	int size = m_StudentVector.size();
	string existStudentID;
	for (int i = 0; i < size; i++)
	{
		((Student*) m_StudentVector[i])-> GetStudentID(existStudentID);

		if (existStudentID.compare(studentId) == 0)
		{

			ACE_Reactor::instance()->remove_handler(
					((Student*) m_StudentVector[i]),
					ACE_Event_Handler::READ_MASK);

			break;
		}
	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);

	//ACE_Reactor::instance()->cancel_timer(student, 0);
}

/**************************************************************************************************
 * Function Name	: RemoveHandleAll
 * Description		: Remove Handle from the ACE_Reactor::instance().
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::RemoveHandleAll()
{
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	int size = m_StudentVector.size();
	for (int i = 0; i < size; i++)
	{
		RemoveHandle(m_StudentVector[i]);
	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	//ACE_Reactor::instance()->cancel_timer(student, 0);
}

/**************************************************************************************************
 * Function Name	: GetStudentList
 * Description		: Get Student List
 * Date				: 08/09/15
 * Parameter		: CIntfData& intfData
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::GetStudentList(CIntfData& intfData)
{
	CSESLog::WriteLine(" CStudentMgr::GetStudentList>>Start");
	std::list<StudentInfo_t> list;
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	int size = m_StudentVector.size();

	for (int i = 0; i < size; i++)
	{
		if (ALLOW == m_StudentVector[i]->GetAllowStatus())
		{
			list.push_back(*(m_StudentVector[i]->GetStudentInfo_t()));
		}
	}

	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	intfData.ParaXmlDoc.setStudentInfoList(list);
	CSESLog::WriteLine(" CStudentMgr::GetStudentList<<End");
}

/**************************************************************************************************
 * Function Name	: GetStudentDetailedInfo
 * Description		: Get Student Detailed Infomation.
 * Date				: 08/09/15
 * Parameter		: std::string& studentID,StudentInfo_t& studentInfo_t
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::GetStudentDetailedInfo(std::string& studentID,
		StudentInfo_t& studentInfo_t)
{
	CSESLog::WriteLine(" CStudentMgr::GetStudentDetailedInfo>>Start");
	std::string existStudentID;

	bool bReturn = false;
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	int size = m_StudentVector.size();

	for (int i = 0; i < size; i++)
	{
		m_StudentVector[i]->GetStudentID(existStudentID);
		if (0 == existStudentID.compare(studentID))
		{
			studentInfo_t = (*(m_StudentVector[i]->GetStudentInfo_t()));
			bReturn = true;

			break;

		}
	}

	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	CSESLog::WriteLine(" CStudentMgr::GetStudentDetailedInfo<<End");
	return bReturn;
}

/**************************************************************************************************
 * Function Name	: UpdateStudentStatus
 * Description		: Update student status.
 * Date				: 08/09/15
 * Parameter		: std::string& studentID, int iLock,int istates
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::UpdateStudentStatus(std::string& studentID, int iLock,
		int istates)
{

	string log;
	log.append("CStudentMgr::UpdateStudentStatus>>Start:");

	char msg1[10] = "";
	char msg2[10] = "";
	sprintf(msg1, "%d", iLock);
	sprintf(msg2, "%d", istates);
	log.append(msg1);
	log.append(msg2);

	CSESLog::WriteLine(log);

	bool bReturn = false;
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	int size = m_StudentVector.size();
	std::string existStudentID;
	for (int i = 0; i < size; i++)
	{
		m_StudentVector[i]->GetStudentID(existStudentID);
		if (existStudentID.compare(studentID) == 0)
		{
			m_StudentVector[i]->UpdateStudentStatus(iLock, istates);
			bReturn = true;
			break;
		}
	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);

	CSESLog::WriteLine("CStudentMgr::UpdateStudentStatus>>End");
	return bReturn;
}

void CStudentMgr::UpdateLockPolicyData(std::string& studentID,
		long int lastUpdateTime, std::string deployname)
{
	CSESLog::WriteLine("CStudentMgr::UpdateLockPolicyData>>Start");
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	int size = m_StudentVector.size();
	std::string existStudentID;
	for (int i = 0; i < size; i++)
	{
		m_StudentVector[i]->GetStudentID(existStudentID);
		if (existStudentID.compare(studentID) == 0)
		{
			m_StudentVector[i]->UpdateLockPolicyData(lastUpdateTime, deployname);
			break;
		}
	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);

	CSESLog::WriteLine("CStudentMgr::UpdateLockPolicyData>>End");
}

/**************************************************************************************************
 * Function Name	: SetStudentDetailedInfo
 * Description		: Set student detailed iInfomation.
 * Date				: 08/09/15
 * Parameter		: std::string& studentID,StudentInfo_t& studentInfo_t
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::SetStudentDetailedInfo(std::string& studentID,
		StudentInfo_t& studentInfo_t)
{
	bool bReturn = false;
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	int size = m_StudentVector.size();
	std::string existStudentID;
	for (int i = 0; i < size; i++)
	{
		m_StudentVector[i]->GetStudentID(existStudentID);
		if (existStudentID.compare(studentID))
		{
			m_StudentVector[i]->SetStudentInfo_t(studentInfo_t);
			bReturn = true;
			break;
		}
	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);

	return bReturn;
}

bool CStudentMgr::UpdateLockPolicy(std::string& studentID,
		std::string lockPolicy)
{
	bool bReturn = false;
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	int size = m_StudentVector.size();
	std::string existStudentID;
	for (int i = 0; i < size; i++)
	{
		m_StudentVector[i]->GetStudentID(existStudentID);
		if (0 == existStudentID.compare(studentID))
		{
			m_StudentVector[i]->SetLockPolicy(lockPolicy);
			bReturn = true;
			break;
		}
	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);

	return bReturn;
}

bool CStudentMgr::GetLockPolicy(std::string& studentID, std::string& lockPolicy)
{
	CSESLog::WriteLine(" CStudentMgr::GetLockPolicy>>Start");
	std::string existStudentID;

	bool bReturn = false;
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	int size = m_StudentVector.size();

	for (int i = 0; i < size; i++)
	{
		m_StudentVector[i]->GetStudentID(existStudentID);
		if (0 == existStudentID.compare(studentID))
		{
			m_StudentVector[i]->GetLockPolicy(lockPolicy);
			bReturn = true;
			break;
		}
	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	CSESLog::WriteLine(" CStudentMgr::GetLockPolicy<<End");
	return bReturn;
}

/**************************************************************************************************
 * Function Name	: HandleHeartBeat(Not use any more)
 * Description		: Handle heartbeat
 * Date				: 08/09/15
 * Parameter		: CIntfData & intfData
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::HandleHeartBeat(CIntfData & intfData)
{
	std::list<StudentInfo_t> list;
	StudentInfo_t newStudentInfo_t;
	std::string studentID;
	std::string existStudentID;
	intfData.GetStudentID(studentID);
	bool bLocked, bHostName, bUserName;//, bName
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	int size = m_StudentVector.size();

	for (int i = 0; i < size; i++)
	{
		m_StudentVector[i]->GetStudentID(existStudentID);
		if (existStudentID.compare(studentID))
		{
			StudentInfo_t* studentInfo_t;
			studentInfo_t = (m_StudentVector[i]->GetStudentInfo_t());
			intfData.ParaXmlDoc.getStudentInfoList(list);
			newStudentInfo_t = ((StudentInfo_t) list.front());
			bLocked = (studentInfo_t->bLocked == newStudentInfo_t.bLocked);

			bHostName = (studentInfo_t->hostname == newStudentInfo_t.hostname);
			bUserName = (studentInfo_t->username == newStudentInfo_t.username);
			if (bLocked && bHostName && bUserName)
			{
				//				ACE_Reactor::instance()->cancel_timer(m_StudentVector[i], 0);
				//				ACE_Reactor::instance()->schedule_timer(m_StudentVector[i], 0,
				//						ACE_Time_Value(STUDENT_TIMEOUT));
			}
			else
			{
				//beta HandleHeartBeat
				//COperationManagerCallBack()
			}
		}
	}

	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	intfData.ParaXmlDoc.setStudentInfoList(list);
	return true;
}

/**************************************************************************************************
 * Function Name	: IsTimeOut
 * Description		: whether timeout.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::IsTimeOut()
{
	//Not use any more
	return true;
}

/**************************************************************************************************
 * Function Name	: UpdateStudent (Not use any more)
 * Description		: Update Student.
 * Date				: 08/09/15
 * Parameter		: const CIntfData & intfData
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::UpdateStudent(const CIntfData & intfData)
{
	// Not use any more
	return;
}

/**************************************************************************************************
 * Function Name	: Send
 * Description		: Send net msssage.
 * Date				: 08/09/15
 * Parameter		: const CIntfData & intfData
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::Send(const CIntfData & intfData)
{
	CSESLog::WriteLine("CStudentMgr::Send>>Start");

	std::string messageName;
	intfData.GetMessage(messageName);
	CSESLog::WriteLine(messageName);
	std::string existStudentID;
	intfData.GetStudentID(existStudentID);
	CSESLog::WriteLine(existStudentID);
	std::string studentID;
	bool bReturn = false;
	std::string msg;
	intfData.toString(msg);
	unsigned long iLen = 0;
	unsigned char* pucStr = NULL;

	if (CSESDataTools::Compress(msg, &pucStr, iLen))
	{

		ACE_OS::thread_mutex_lock(&mc_mgr_lock);
		int size = m_StudentVector.size();
		for (int i = 0; i < size; i++)
		{

			((Student*) m_StudentVector[i])-> GetStudentID(studentID);

			if (existStudentID.compare(studentID) == 0)
			{

				((Student*) m_StudentVector[i])->Send(pucStr, iLen);

				bReturn = true;
				break;
			}
		}
		ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
		delete pucStr;
		//CSESDataTools::Uncompress(&pucStr, msg, iLen);
		CSESLog::WriteLine(msg);
	}

	CSESLog::WriteLine("CStudentMgr::Send<<End");
	return bReturn;
}

/**************************************************************************************************
 * Function Name	: SendAll
 * Description		: Send net msssage.
 * Date				: 08/09/15
 * Parameter		: const CIntfData & intfData
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::SendAll(const CIntfData & intfData)
{
	CSESLog::WriteLine("CStudentMgr::SendAll>>Start");

	std::string messageName;
	intfData.GetMessage(messageName);
	CSESLog::WriteLine(messageName);
	std::string msg;
	intfData.toString(msg);
	bool bReturn = true;

	unsigned long iLen = 0;
	unsigned char* pucStr = NULL;

	if (CSESDataTools::Compress(msg, &pucStr, iLen))
	{
		string stuID;

		ACE_OS::thread_mutex_lock(&mc_mgr_lock);
		int size = m_StudentVector.size();
		for (int i = 0; i < size; i++)
		{
			((Student*) m_StudentVector[i])->Send(pucStr, iLen);
			m_StudentVector[i]->GetStudentID(stuID);
			CSESLog::WriteLine(stuID);
		}
		delete pucStr;
		ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	}

	CSESLog::WriteLine("CStudentMgr::SendAll<<End");
	return bReturn;
}

/**************************************************************************************************
 * Function Name	: KickOffAllStudent
 * Description		: KickOffAllStudent
 * Date				: 08/09/15
 * Parameter		: const CIntfData & intfData
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::KickOffAllStudent(const CIntfData& bybCIntfData)
{
	CSESLog::WriteLine("CStudentMgr::KickOffAllStudent<<start");
	bool bReturn = true;
	string msg;
	bybCIntfData.toString(msg);
	unsigned long iLen = 0;
	unsigned char* pucStr = NULL;

	if (CSESDataTools::Compress(msg, &pucStr, iLen))
	{
		ACE_OS::thread_mutex_lock(&mc_mgr_lock);
		int size = m_StudentVector.size();
		for (int i = 0; i < size; i++)
		{
			Student* pStudent = m_StudentVector[i];
			RemoveHandle(pStudent);

			pStudent->Send(pucStr, iLen);
		}
		for (int i = 0; i < size; i++)
		{
			//delete m_StudentVector[i];
			m_StudentVector[i]->Close();
			m_StudentVector[i]->Schedule_timer();
		}
		m_StudentVector.clear();
		ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
		delete pucStr;
	}
	//delete pucStr;

	CSESLog::WriteLine("CStudentMgr::KickOffAllStudent<<End");
	return bReturn;
}

/**************************************************************************************************
 * Function Name	: KickOffStudentList
 * Description		: KickOffStudentList
 * Date				: 08/09/15
 * Parameter		: const CIntfData & intfData
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::KickOffStudentList(const CIntfData& bybCIntfData,
		list<string>& strlist)
{
	CSESLog::WriteLine("CStudentMgr::KickOffStudentList<<Start");
	bool bReturn = true;
	string msg;
	bybCIntfData.toString(msg);
	unsigned long iLen = 0;
	unsigned char* pucStr = NULL;

	int iSize = 0;
	iSize = m_StudentVector.size();
	list<string>::iterator itBegin;
	list<string>::iterator itEnd;
	int iListSize = strlist.size();
	string existStudentId;
	bool bFound = false;
	// make two
	if (CSESDataTools::Compress(msg, &pucStr, iLen))
	{
		ACE_OS::thread_mutex_lock(&mc_mgr_lock);

		while ((iListSize > 0) && (m_StudentVector.size() > 0))
		{
			std::vector<Student*>::iterator startIterator =
					m_StudentVector.begin();
			std::vector<Student*>::iterator endIterator = m_StudentVector.end();
			bFound = false;
			for (startIterator = m_StudentVector.begin(); startIterator
					!= endIterator; startIterator++)
			{
				(*startIterator)->GetStudentID(existStudentId);
				itBegin = strlist.begin();
				itEnd = strlist.end();
				for (; itBegin != itEnd; ++itBegin)
				{
					if (0 == (*itBegin).compare(existStudentId))
					{
						RemoveHandle(*startIterator);
						(*startIterator)->Send(pucStr, iLen);
						(*startIterator)->Close();
						(*startIterator)->Schedule_timer();
						//delete (*startIterator);
						//m_StudentVector.erase(*startIterator)
						strlist.remove(existStudentId);
						bFound = true;
						m_StudentVector.erase(startIterator);
						break;
					}
				}
				iListSize--;
				if (bFound)
				{
					break;
				}
			}
		}
		ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
		delete pucStr;
	}
	CSESLog::WriteLine("CStudentMgr::KickOffStudentList<<End");
	return bReturn;
}

/**************************************************************************************************
 * Function Name	: COperationManagerCallBack
 * Description		: COperationManagerCallBack.
 * Date				: 08/09/15
 * Parameter		: CIntfData& intfData
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::COperationManagerCallBack(CIntfData& intfData)
{

	if (m_pCOperationManager != NULL)
	{
		m_pCOperationManager->StuMgrCallback(intfData);

	}
	return;

}

/**************************************************************************************************
 * Function Name	: COperationManagerDisconnectCallBack
 * Description		: COperationManager disconnectCallBack.
 * Date				: 08/09/15
 * Parameter		: std::string& studentID
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void CStudentMgr::COperationManagerDisconnectCallBack(std::string& studentID)
{
	CSESLog::WriteLine(
			"CStudentMgr::COperationManagerDisconnectCallBack()>>Start");
	if (NULL != m_pCOperationManager)
	{
		m_pCOperationManager->StuMgrDisconnectCallback(studentID);
	}
	else
	{
		CSESLog::WriteLine(
				"CStudentMgr::COperationManagerDisconnectCallBack()<<m_pCOperationManager==NULL");
	}
	CSESLog::WriteLine(
			"CStudentMgr::COperationManagerDisconnectCallBack()<<End");
	return;

}

bool CStudentMgr::GetStudentforNotifyTeacher(StudentInfo_t& studentInfo_t)
{
	CSESLog::WriteLine(" CStudentMgr::GetStudentforNotifyTeacher>>Start");

	bool bReturn = false;
	ACE_OS::thread_mutex_lock(&mc_mgr_lock);
	int size = m_StudentVector.size();
	int iAllowFlag = 0;
	int iNewStudent = -1;
	for (int i = 0; i < size; i++)
	{
		iAllowFlag = m_StudentVector[i]->GetAllowStatus();
		if (WAITING == iAllowFlag)
		{
			//don't send new request if a request is waiting for allow.
			bReturn = false;
			break;
		}
		if (QUEUE == iAllowFlag)
		{
			// find new request for allowing teacher.
			//first in, first request
			if (false == bReturn)
			{
				studentInfo_t = (*(m_StudentVector[i]->GetStudentInfo_t()));
				bReturn = true;
				iNewStudent = i;
			}
		}
	}
	if (true == bReturn)
	{
		m_StudentVector[iNewStudent]->SetAllowStatus(WAITING);
	}
	ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
	CSESLog::WriteLine(" CStudentMgr::GetStudentforNotifyTeacher<<End");
	return bReturn;
}
/**************************************************************************************************
 * Function Name	: ControlNewStudent
 * Description		: Control NewStudent
 * Date				: 08/09/15
 * Parameter		: std::string& studentID, bool bAllow, CIntfData& cIntfData
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CStudentMgr::ControlNewStudent(std::string& studentID, bool bAllow,
		CIntfData& cIntfData)
{
	CSESLog::WriteLine(" CStudentMgr::ControlNewStudent>>Start");
	bool bReturn = false;
	std::string msg;
	cIntfData.toString(msg);
	unsigned long iLen = 0;
	unsigned char* pucStr = NULL;

	if (CSESDataTools::Compress(msg, &pucStr, iLen))
	{
		ACE_OS::thread_mutex_lock(&mc_mgr_lock);

		std::vector<Student*>::iterator startIterator;

		std::string existStudentID;
		startIterator = m_StudentVector.begin();
		int size = m_StudentVector.size();

		for (int i = 0; i < size; i++)
		{

			((Student*) m_StudentVector[i])-> GetStudentID(existStudentID);

			if (0 == existStudentID.compare(studentID))
			{

				if (bAllow)
				{
					//reset time
					int iTime;
					time((time_t*) &iTime);
					(((Student*) m_StudentVector[i])->GetStudentInfo_t())->start_time
							= iTime;
					((Student*) m_StudentVector[i])->SetAllowStatus(ALLOW);
					//(((Student*) m_StudentVector[i])->GetStudentInfo_t())->status = SES_STU_CONNECT;
					m_StudentVector[i]->Send(pucStr, iLen);
					//bReturn = true;

				}
				else
				{
					RemoveHandle(m_StudentVector[i]);
					m_StudentVector[i]->Send(pucStr, iLen);
					//delete (*startIterator);
					m_StudentVector.erase(startIterator);
				}
				bReturn = true;

				break;
			}
			startIterator++;

		}

		ACE_OS::thread_mutex_unlock(&mc_mgr_lock);
		delete pucStr;
	}
	CSESLog::WriteLine(" CStudentMgr::ControlNewStudent>>End");
	return bReturn;
}
bool CStudentMgr::IsStudentExist(std::string& studentID)
{
	int size = m_StudentVector.size();
	std::string existStudentID;
	for (int i = 0; i < size; i++)
	{
		((Student*) m_StudentVector[i])-> GetStudentID(existStudentID);

		if (0 == existStudentID.compare(studentID))
		{
			return true;
		}
	}
	return false;
}
