/**************************************************************************************************
 * File Name	: Student.cpp
 * Created		: 08/09/15
 * Author		: ChenWei
 * Model			: TSD
 * Description	: Student.
 **************************************************************************************************/
#include "StudentMgr.h"
#include "Student.h"

using namespace IPCAPI;
/**************************************************************************************************
 * Function Name	: Student
 * Description		: Construct Student
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
Student::Student()
{
	conn = NULL;
	m_iDisconnectStatus = CONNECTION_CONNECTED;
	m_iAllowStatus = QUEUE;
	m_MsgNodeList.clear();
	//	m_SendMsgList = NULL;
	//	m_SendMsgList = new std::list<std::string>();
	iSend = 0;
	iOutPut = 0;
	m_bHandle_input = 0;
	m_bDel = 0;
}

/**************************************************************************************************
 * Function Name	: ~Student
 * Description		: Destory Student
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
Student::~Student()
{
	Close();
	m_SendMsgListLock.acquire();
	ACE_Reactor::instance()->remove_handler(this, ACE_Event_Handler::WRITE_MASK);
	while (m_MsgNodeList.size())
	{
		delete m_MsgNodeList.front();
		m_MsgNodeList.pop_front();
	}
	m_SendMsgList.clear();
	if (NULL != conn)
	{
		delete conn;
		conn = NULL;
	}
	m_SendMsgListLock.release();
}

/**************************************************************************************************
 * Function Name	: Close
 * Description		: Close connection.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void Student::Close()
{
	CSESLog::WriteLine(
			"ACE_Thread::self(),Student::Close>>start ACE_Thread::self(),");
	int iTry = 0;
	//int iSizeSendMsgList = 0;

	m_SendMsgListLock.acquire();
	if (conn != NULL)
	{
		ACE_Reactor::instance()->remove_handler(this,
				ACE_Event_Handler::READ_MASK);
		//		while (m_SendMsgList.size() > 0 && iTry++ < 3)
		//		{
		//			m_SendMsgListLock.release();
		//			usleep(100000);
		//			m_SendMsgListLock.acquire();
		//			iSizeSendMsgList = m_SendMsgList.size();
		//		}
		//		CSESLog::WriteLine(iTry, "Student::Close>>iTry:");
		iTry = 0;
		while (m_MsgNodeList.size() > 0 && iTry++ < 3)
		{
			m_SendMsgListLock.release();
			usleep(100000);
			m_SendMsgListLock.acquire();

		}

		CSESLog::WriteLine(iTry, "Student::Close>>iTry:");

		ACE_Reactor::instance()->remove_handler(this,
				ACE_Event_Handler::WRITE_MASK);
		while (m_MsgNodeList.size())
		{
			delete m_MsgNodeList.front();
			m_MsgNodeList.pop_front();
		}
		m_SendMsgList.clear();

		//		m_SendMsgListLock.acquire();
		//		m_SendLock.acquire();
		//		m_RecvLock.acquire();
		conn->Disconnect();

		//		if (iTry > 2)
		//		{
		CSESLog::WriteLine(
				"ACE_Thread::self(),Student::Close>>usleep(10); ACE_Thread::self(),");
		//usleep(1000);
		//		}
		//		m_RecvLock.release();
		//		m_SendLock.release();
		//		m_SendMsgListLock.release();
	}
	m_SendMsgListLock.release();
	CSESLog::WriteLine(
			"ACE_Thread::self(),		Student::Close>>ed ACE_Thread::self(),");
}

/**************************************************************************************************
 * Function Name	: Recv
 * Description		: Recv network message.
 * Date				: 08/09/15
 * Parameter		: std::string& msg
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool Student::Recv(std::string& msg)
{
	if (NULL != conn)
	{
		return conn->Recv(msg);
	}
	else
	{
		return false;
	}
}

/**************************************************************************************************
 * Function Name	: Send
 * Description		:
 * Date				: 08/09/15
 * Parameter		: std::string& msg
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
//bool Student::Send(std::string& msg, int iTimeout)
//{
//	CSESLog::WriteLine("Student::Send>>start");
//
//	bool bReturn = 1;
//	if (NULL != conn)
//	{
//		bReturn = conn->Send(msg, iTimeout);
//	}
//	else
//	{
//		bReturn = false;
//	}
//	CSESLog::WriteLine("Student::Send>> end");
//	return true;
//
//}

/**************************************************************************************************
 * Function Name	: Send
 * Description		:
 * Date				: 08/09/15
 * Parameter		: std::string& msg
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
//bool Student::Send(std::string& msg)
//{
//	CSESLog::WriteLine("Student::Send>>start");
//	iSend++;
//	m_SendMsgListLock.acquire();
//	if (m_SendMsgList.size() < 2)
//	{
//		if (NULL != conn)
//		{
//			ACE_Reactor::instance()->register_handler(this,
//					ACE_Event_Handler::WRITE_MASK);
//		}
//	}
//	m_SendMsgList.push_back(msg);
//	m_SendMsgListLock.release();
//	CSESLog::WriteLine(iSend, "Student::Send>> end");
//	return true;
//}

/**************************************************************************************************
 * Function Name	: Send
 * Description		:
 * Date				: 08/09/15
 * Parameter		: std::string& msg
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool Student::Send(unsigned char* pucStr, unsigned long iLen)
{
	CSESLog::WriteLine("Student::Send>>start");
	//
	m_SendMsgListLock.acquire();
	iSend++;
	if (NULL != conn)
	{
		if (conn->IsConnect())
		{
			if (0 == m_MsgNodeList.size())
			{

				ACE_Reactor::instance()->register_handler(this,
						ACE_Event_Handler::WRITE_MASK);
			}
			int iSize = iLen;
			CSESLog::WriteLine(iSize, "Student::Send new Node");
			Node* node = new Node(pucStr, iLen);
			m_MsgNodeList.push_back(node);
			CSESLog::WriteLine(iSend, "Student::Send>> times:");
		}
	}
	m_SendMsgListLock.release();
	CSESLog::WriteLine("Student::Send>> end");
	return true;
}
//}
//else
//{
//	if (NULL != conn)
//	{
//		if (conn->IsConnect())
//		{
//			int iSize = iLen;
//			CSESLog::WriteLine(iSize, "Student::Send new Node");
//			Node* node = new Node(pucStr, iLen);
//
//			m_MsgNodeList.push_back(node);
//			CSESLog::WriteLine(iSend, "Student::Send>> times:");
//		}
//	}
//
//}


/**************************************************************************************************
 * Function Name	: Send
 * Description		:
 * Date				: 08/09/15
 * Parameter		: std::string& msg
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
//bool Student::Send(unsigned char* pucMsg, int iSize, int iTimeout)
//{
//	CSESLog::WriteLine("Student::Send>>start");
//	iSend++;
//	m_SendMsgListLock.acquire();
//	if ( m_SendMsgList->size()<2)
//	{
//		if (NULL != conn)
//		{
//
//			ACE_Reactor::instance()->register_handler(this,
//					ACE_Event_Handler::WRITE_MASK);
//		}
//	}
//	m_SendMsgList->push_back(msg);
//	m_SendMsgListLock.release();
//	CSESLog::WriteLine(iSend, "Student::Send>> end");
//	return true;
//}

/**************************************************************************************************
 * Function Name	: SetConn
 * Description		: Set connection
 * Date				: 08/09/15
 * Parameter		: CNetSSLClientWrapper& cNetSSLClientWrapper
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void Student::SetConn(CNetSSLClientWrapper& cNetSSLClientWrapper)
{

	conn = &cNetSSLClientWrapper;
}

/**************************************************************************************************
 * Function Name	: GetStudentID
 * Description		: Get studentID
 * Date				: 08/09/15
 * Parameter		: std::string & studentID
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void Student::GetStudentID(std::string & studentID) const
{
	studentID = m_StudentID;
}

/**************************************************************************************************
 * Function Name	: SetStudentID
 * Description		: Set studentID.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void Student::SetStudentID(const std::string & id)
{
	m_StudentID = id;
}

/**************************************************************************************************
 * Function Name	: GetStudentInfo_t
 * Description		: Get m_StudentInfo_t
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
StudentInfo_t* Student::GetStudentInfo_t()
{
	return &m_StudentInfo_t;
}

/**************************************************************************************************
 * Function Name	: SetStudentInfo_t
 * Description		: SetStudentInfo_t
 * Date				: 08/09/15
 * Parameter		: const StudentInfo_t& studentInfo_t
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void Student::SetStudentInfo_t(const StudentInfo_t& studentInfo_t)
{
	m_StudentInfo_t = studentInfo_t;
}

/**************************************************************************************************
 * Function Name	: UpdateStudentStatus
 * Description		: Update student's status
 * Date				: 08/09/15
 * Parameter		: int iLock, int istates
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void Student::UpdateStudentStatus(int iLock, int istates)
{
	m_StudentInfo_t.bLocked = iLock;
	m_StudentInfo_t.status = istates;
}

void Student::UpdateLockPolicyData(long int lastUpdateTime,
		std::string deployname)
{
	m_StudentInfo_t.lastUpdateTime = lastUpdateTime;
	m_StudentInfo_t.deployerName = deployname;
}

int Student::handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask)
{
	CSESLog::WriteLine("Student::handle_close ");

	return -1;
}

int Student::handle_signal(int signum, siginfo_t * pSig, ucontext_t * pu)
{
	CSESLog::WriteLine("Student::handle_signal>> ERR");

	return 0;
}

/**************************************************************************************************
 * Function Name	: handle_input
 * Description		: handle_input
 * Date				: 08/09/15
 * Parameter		: ACE_HANDLE handle
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
int Student::handle_exception(ACE_HANDLE handle)
{
	CSESLog::WriteLine("Student::handle_exception>> ERR");

	return 0;
}

/**************************************************************************************************
 * Function Name	: handle_input
 * Description		: handle_input
 * Date				: 08/09/15
 * Parameter		: ACE_HANDLE handle
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
int Student::handle_input(ACE_HANDLE handle)
{

	CSESLog::WriteLine(
			"ACE_Thread::self()		Student::handle_input>>Start ACE_Thread::self(),");
	//sleep(8);
	m_RectorLock.acquire();
	CSESLog::WriteLine("Student::handle_input m_RectorLock.acquire()");
	std::string delStudentID = m_StudentID;
	time(&m_TimerOld);

	std::string sed = "Student::handle_input:Send this";
	std::string recvMsg;
	int recvSize = 0;
	int iReturn = 0;
	//	m_bHandle_input = 1;
	CSESLog::WriteLine(m_TimerOld, "Student::handle_input:time:");
	do
	{
		m_RecvLock.acquire();

		if (NULL != conn)
		{
			recvSize = conn->Recv(recvMsg);
		}
		else
		{
			iReturn = -1;
		}
		m_RecvLock.release();
		if (-1 == iReturn)
		{
			break;
		}

		if (recvSize <= 0)
		{
			ACE_Reactor::instance()->remove_handler(this,
					ACE_Event_Handler::READ_MASK);
			CSESLog::WriteLine(
					"ACE_Thread::self()		Student::handle_input <=0: ACE_Thread::self(),");
			CSESLog::WriteLine(ACE_OS_String::strerror(errno), CSESLog::WARNING);
			CSESLog::WriteLine(
					"ACE_Thread::self(),CStudentMgr::instance()->COperationManagerDisconnectCallBack>>Start ACE_Thread::self(),");

			CStudentMgr::instance()->COperationManagerDisconnectCallBack(
					delStudentID);
			CSESLog::WriteLine(
					"ACE_Thread::self(),		CStudentMgr::instance()->COperationManagerDisconnectCallBack<<End ACE_Thread::self(),");
			iReturn = 0;
		}
		else
		{
			CIntfData cIntfData;
			if (cIntfData.load(recvMsg))
			{
				cIntfData.SetStudentID(this->m_StudentID);
				CSESLog::WriteLine(
						"ACE_Thread::selfCStudentMgr::instance()->COperationManagerCallBack>>Start ACE_Thread::self(),");
				CStudentMgr::instance()->COperationManagerCallBack(cIntfData);
				CSESLog::WriteLine(
						"ACE_Thread::selfCStudentMgr::instance()->COperationManagerCallBack<<End ACE_Thread::self(),");
			}
			iReturn = 0;

		}
	} while (0);
	//	m_bHandle_input = 0;
	CSESLog::WriteLine("Student::handle_input<<End m_RectorLock.release()");
	m_RectorLock.release();
	CSESLog::WriteLine(
			"ACE_Thread::self(),Student::handle_input<<End ACE_Thread::self(),");
	return iReturn;
}

/**************************************************************************************************
 * Function Name	: handle_output
 * Description		: handle_output
 * Date				: 08/09/15
 * Parameter		: ACE_HANDLE handle
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
int Student::handle_output(ACE_HANDLE handle)
{
	CSESLog::WriteLine(
			"ACE_Thread::self(),Student::handle_output>>Start ACE_Thread::self(),");
	//	sleep(5);
	m_RectorLock.acquire();
	CSESLog::WriteLine("Student::handle_output>>Start m_RectorLock.acquire();");
	//	CSESLog::WriteLine("Student::handle_output>>Start get m_StudentID");
	//sleep(8);
	int iReturn = 0;
	std::string delStudentID;
	try
	{

		int iSizeSendMsgList = 0;

		do
		{

			if (conn == NULL)
			{
				//			ACE_Reactor::instance()->remove_handler(this,
				//					ACE_Event_Handler::WRITE_MASK);
				//			CSESLog::WriteLine("Student::handle_output m_SendMsgListLock.acquire() Start");
				//			m_SendMsgListLock.acquire();
				//			CSESLog::WriteLine("Student::handle_output m_SendMsgListLock.acquire() ed");
				//			while (m_MsgNodeList.size())
				//			{
				//				delete m_MsgNodeList.front();
				//				m_MsgNodeList.pop_front();
				//			}
				//			m_MsgNodeList.clear();
				//			m_SendMsgListLock.release();
				CSESLog::WriteLine("Student::handle_output conn == NULL",
						CSESLog::FATAL);
				break;
			}
			m_SendMsgListLock.acquire();

			iSizeSendMsgList = m_MsgNodeList.size();

			if (0 == iSizeSendMsgList)
			{
				ACE_Reactor::instance()->remove_handler(this,
						ACE_Event_Handler::WRITE_MASK);
				CSESLog::WriteLine(
						"ACE_Thread::selfStudent::handle_output 0 == iSizeSendMsgList ACE_Thread::self(),");
				m_SendMsgListLock.release();
				break;
			}
			delStudentID = m_StudentID;
			//		if (1 == iSizeSendMsgList)
			//		{
			//			ACE_Reactor::instance()->remove_handler(this,
			//					ACE_Event_Handler::WRITE_MASK);
			//
			//		}
			//int im_MsgNodeListSize=m_MsgNodeList.size();
			unsigned char* pc = m_MsgNodeList.front()->m_pucStr;
			unsigned long ul = m_MsgNodeList.front()->m_iLen;
			//Node node(m_MsgNodeList.front()->m_pucStr, m_MsgNodeList.front()->m_iLen);
			//DO not popup
			//m_MsgNodeList.pop_front();


			string unCompress;
			//CSESDataTools::Uncompress(node.m_pucStr, unCompress, node.m_iLen);

			//CSESLog::WriteLine(unCompress);
			m_SendMsgListLock.release();
			m_SendLock.acquire();
			iOutPut++;
			int iSendSize = conn->Send(pc, ul);
			string strOut;
			CSESDataTools::Uncompress(&pc, strOut, ul);
			CSESLog::WriteLine(iOutPut, "Student::handle_output times::");
			CSESLog::WriteLine(strOut);
			//sleep(5);
			m_SendLock.release();

			m_SendMsgListLock.acquire();
			if (m_MsgNodeList.size())
			{
				delete m_MsgNodeList.front();
				m_MsgNodeList.pop_front();
			}
			//		else
			//		{
			//			iReturn = -1;
			//			break;
			//		}
			m_SendMsgListLock.release();
			if (iSendSize <= 0)
			{
				ACE_Reactor::instance()->remove_handler(this,
						ACE_Event_Handler::WRITE_MASK);
				//			m_SendMsgListLock.acquire();
				//			while (m_MsgNodeList.size())
				//			{
				//				delete m_MsgNodeList.front();
				//				m_MsgNodeList.pop_front();
				//			}
				//			m_SendMsgList.clear();
				//			m_SendMsgListLock.release();
				CSESLog::WriteLine(
						"ACE_Thread::selfStudent::handle_output <=0: ACE_Thread::self(),");
				CSESLog::WriteLine(ACE_OS_String::strerror(errno),
						CSESLog::WARNING);
				CSESLog::WriteLine(
						"CStudentMgr::instance()->COperationManagerDisconnectCallBack>>Start");

				CStudentMgr::instance()->COperationManagerDisconnectCallBack(
						delStudentID);

				CSESLog::WriteLine(
						"CStudentMgr::instance()->COperationManagerDisconnectCallBack<<End");

			}

		} while (0);
		//	if (0 == iReturn)
		//	{
		//		m_SendMsgListLock.release();
		//	}
	} catch (...)
	{
		CSESLog::WriteLine("-------------------------------------------",
				CSESLog::FATAL);
		CSESLog::WriteLine("Student::handle_output catch", CSESLog::FATAL);
		CSESLog::WriteLine("------------------------------------------",
				CSESLog::FATAL);
	}
	CSESLog::WriteLine("Student::handle_output m_RectorLock.release()");
	m_RectorLock.release();
	CSESLog::WriteLine("Student::handle_output<<End:");
	return iReturn;
}

/**************************************************************************************************
 * Function Name	: handle_timeout
 * Description		: handle_timeout
 * Date				: 08/09/15
 * Parameter		: ACE_HANDLE handle
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
int Student::handle_timeout(const ACE_Time_Value &current_time, const void *act)
{
	CSESLog::WriteLine("Student::handle_timeout<<start:");
	m_RectorLock.acquire();
	CSESLog::WriteLine("Student::handle_timeout m_RectorLock.acquire();");
	string stuID = m_StudentID;
	delete this;
	//CStudentMgr::instance()->DelStudent(stuID);
	m_RectorLock.release();
	CSESLog::WriteLine("Student::handle_timeout<<ed:");
	return 0;
}
/**************************************************************************************************
 * Function Name	: Schedule_timer
 * Description		: Schedule_timer Handle from the ACE_Reactor::instance().
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
void Student::Schedule_timer()
{
	ACE_Reactor::instance()->schedule_timer(this, 0, ACE_Time_Value(0,
			DELSTUDENT_TIMEOUT));
}
//int Student::handle_output(ACE_HANDLE handle)
//{
//	CSESLog::WriteLine("Student::handle_output>>Start");
//
//	int iReturn = 0;
//	int iSizeSendMsgList = 0;
//	do
//	{
//
//		if (conn == NULL)
//		{
//			iReturn = -1;
//			break;
//		}
//
//		string msg;
//
//		m_SendMsgListLock.acquire();
//
//		if (conn == NULL)
//		{
//			iReturn = -1;
//			m_SendMsgListLock.release();
//			break;
//		}
//
//		if (0 == m_SendMsgList.size())
//		{
//			iReturn = -1;
//			m_SendMsgListLock.release();
//			break;
//		}
//		iSizeSendMsgList = m_SendMsgList.size();
//
//		if (0 == iSizeSendMsgList)
//		{
//			ACE_Reactor::instance()->remove_handler(this,
//					ACE_Event_Handler::WRITE_MASK);
//			m_SendMsgListLock.release();
//			break;
//		}
//
//		if (iSizeSendMsgList > 0)
//		{
//
//			msg = (m_SendMsgList.front());
//			//CSESLog::WriteLine(msg);
//
//		}
//
//		m_SendMsgListLock.release();
//
//		m_SendLock.acquire();
//		int iSendSize = conn->Send(msg);
//		m_SendLock.release();
//		m_SendMsgListLock.acquire();
//		m_SendMsgList.pop_front();
//		m_SendMsgListLock.release();
//
//		if (iSendSize <= 0)
//		{
//			m_SendMsgListLock.acquire();
//			ACE_Reactor::instance()->remove_handler(this,
//					ACE_Event_Handler::WRITE_MASK);
//			m_SendMsgList.clear();
//
//			CSESLog::WriteLine("Student::handle_output <=0:");
//			CSESLog::WriteLine(ACE_OS_String::strerror(errno), CSESLog::WARNING);
//			CSESLog::WriteLine(
//					"CStudentMgr::instance()->COperationManagerDisconnectCallBack>>Start");
//			std::string delStudentID = m_StudentID;
//			CStudentMgr::instance()->COperationManagerDisconnectCallBack(
//					delStudentID);
//			m_SendMsgListLock.release();
//			CSESLog::WriteLine(
//					"CStudentMgr::instance()->COperationManagerDisconnectCallBack<<End");
//			iReturn = 0;
//
//		}
//
//	} while (0);
//	iOutPut++;
//	CSESLog::WriteLine(iOutPut, "Student::handle_output<<End:");
//	return iReturn;
//}

/**************************************************************************************************
 * Function Name	: get_handle
 * Description		: get_handle
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
ACE_HANDLE Student::get_handle(void) const
{
	ACE_HANDLE iReturn = -1;
	try
	{
		if (NULL != conn)
		{
			iReturn = conn->GetHandle();
		}
		else
		{
			CSESLog::WriteLine("Student::get_handle return -1 Error<<End",
					CSESLog::ERROR);
		}
	} catch (...)
	{
		iReturn = -1;
	}
	return iReturn;
}

int Student::MsgListSize()
{
	m_SendMsgListLock.acquire();
	int iSize = m_SendMsgList.size();
	m_SendMsgListLock.release();
	return iSize;

}

void Student::SetDisconnectStatus(int DisconnectStatus)
{
	m_iDisconnectStatus = DisconnectStatus;
}
int Student::GetDisconnectStatus()
{
	return m_iDisconnectStatus;
}
void Student::SetAllowStatus(int AllowStatus)
{
	m_iAllowStatus = AllowStatus;
}
int Student::GetAllowStatus()
{
	return m_iAllowStatus;
}

void Student::SetLockPolicy(std::string lockPolicy)
{
	this->m_LockScheduleData.Clear();
	this->m_LockScheduleData.LoadFromString(lockPolicy);
}

void Student::GetLockPolicy(std::string& lockPolicy)
{
	this->m_LockScheduleData.Save2String(lockPolicy);
}
