#include "ModeSlave.h"
#include "GetSource.h"
#include "Logger.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>


// class CServiceMode : Service Master Mode class
CSlaveMode::CSlaveMode(CProcessSocketControl * pclient)
	: CServiceMode(pclient)
{
}

CSlaveMode::~CSlaveMode()
{
	if (!IsEmpytSycnList())
	{
		m_synclist.GetFirst().UnlinkFile();
	}
}

bool CSlaveMode::CreateSyncList(CReqSlaveData &d)
{
	return m_synclist.CreateList(d);
}

void CSlaveMode::Execute()
{
	std::string strErrorMessage;

	if (IsEmpytSycnList())
	{
		strErrorMessage = "Empty Slave Mode Sync Data";

		// 오류 결과 전송
		m_pclient->SendErrorContentListToMaster( strErrorMessage );
		
		LOG(LERR, "%s", strErrorMessage.c_str());
		return;
	}
	

	// 수행 작업

	// 요청 받은 정보에 대한 source data 추출
	CGetSource slave(m_synclist.GetFirst());
	if (slave.GetSource(CGetSource::SELF_SLAVE_ONLYE) == false)
	{
		strErrorMessage = "Failed Get Source Slave.";

		// 오류 결과 전송
		m_pclient->SendErrorContentListToMaster( strErrorMessage );
		
		LOG( LERR, "%s", strErrorMessage.c_str() );
		return;
	}

	// Send data : 추출된 source data ( 파일명은 file_slave_name 에 저장된 상태 )
	// - 대상 파일 size 확인...
	// - fd open 후
	// - 전송 처리.

	struct stat resultFileStat;
	if( stat( m_synclist.GetFirst().file_slave_name.c_str(), &resultFileStat ) != 0 )
	{
		// 해당 파일에 대한 stat 정보 추출 실패시.
		int errorNum = errno;
		char tempBuffer[1024];
		snprintf( tempBuffer, sizeof( tempBuffer ) - 1, "slave mode result file[%s] stat check fail [%d][%s]"
				  , m_synclist.GetFirst().file_slave_name.c_str()
				  , errorNum, strerror( errorNum ) );

		strErrorMessage = tempBuffer;

		// 오류 결과 전송
		m_pclient->SendErrorContentListToMaster( strErrorMessage );

		LOG( LERR, "%s", strErrorMessage.c_str() );
		return;
	}

	// 파일 size 추출.
	unsigned long long nFileSize = resultFileStat.st_size;
	
	// fd open
	int resultFd = open( m_synclist.GetFirst().file_slave_name.c_str(), O_RDONLY );
	if( resultFd == -1 )
	{
		int errorNum = errno;

		char tempBuffer[1024];
		snprintf( tempBuffer, sizeof( tempBuffer ) - 1, "slave mode result file[%s] open fail [%d][%s]"
				  , m_synclist.GetFirst().file_slave_name.c_str()
				  , errorNum, strerror( errorNum ));

		strErrorMessage = tempBuffer;

		// 오류 결과 전송
		m_pclient->SendErrorContentListToMaster( strErrorMessage );

		LOG( LERR, "%s", strErrorMessage.c_str() );
		return;
	}

	// 파일 전송 처리.
	if( m_pclient->SendResultContentListToMaster( resultFd, nFileSize ) == false )
	{
		// 전송 처리 실패시.. 
		// 상대편에서 재시도 등의 처리를 수행토록 socket 을 close 처리한다.
		LOG( LERR, "slave mode result file[%s] send fail. socket close.", m_synclist.GetFirst().file_slave_name.c_str() );
		m_pclient->Close();
	}
	else
	{
		_LOG( LDBG, "slave mode result file[%s] send OK.", m_synclist.GetFirst().file_slave_name.c_str() );
	}
	
	close( resultFd );

	return;
}
