#include "Synchronization.h"
#include "Logger.h"
#include "RcSyncdRequestData.h"
#include "ProcessSocketControl.h"
#include "ServiceConfig.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

CSynchronization::CSynchronization(CSyncInfo &info)
	: m_syncinfo(info)
{
}

CSynchronization::~CSynchronization()
{
}

int CSynchronization::ExcuteSync()
{
	std::string strMessage;
	std::string strErrorMessage;

	CReqSyncData request;
	request.sync_type = m_syncinfo.sync_type;
	request.start_time = m_syncinfo.start_time;
	request.end_time = m_syncinfo.end_time;
	request.master = m_syncinfo.sync_master;
	request.slave = m_syncinfo.sync_slave;
	
	// get file size 
	struct stat resultFileStat;
	if( stat( m_syncinfo.file_sync_name.c_str(), &resultFileStat ) != 0 )
	{
		// 해당 파일에 대한 stat 정보 추출 실패시.
		int errorNum = errno;
		char tempBuffer[1024];
		
		if( errno != ENOENT )
		{
			snprintf( tempBuffer, sizeof( tempBuffer ) - 1, "sync file mode file[%s] stat check fail [%d][%s]"
					  , m_syncinfo.file_sync_name.c_str()
					  , errorNum, strerror( errorNum ) );

			strErrorMessage = tempBuffer;
			LOG( LERR, "%s", strErrorMessage.c_str() );
			return -1;
		}
		else
		{
			// 파일이 존재 하지 않는 경우는 싱크 대상 목록이 없다는 것이기 때문에 성공으로 간주한다.
			LOG( LINF, "Not exist sync file.[%s]", strErrorMessage.c_str() );
			return 0;
		}
	}

	// check 모드 인 경우 단순 리턴함
	if (m_syncinfo.sync_type > SYNC_TYPE::NORMA_N_ONLY)
		return 1;

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

		char tempBuffer[1024];
		snprintf( tempBuffer, sizeof( tempBuffer ) - 1, "sync file mode result file[%s] open fail [%d][%s]"
				  , m_syncinfo.file_sync_name.c_str()
				  , errorNum, strerror( errorNum ));

		strErrorMessage = tempBuffer;

		LOG( LERR, "%s", strErrorMessage.c_str() );
		return -2;
	}
	
	// Slave rc_syncd 접속 및 content 정보 요청
	CProcessSocketControl slave;
	slave.ConnectTarget(m_syncinfo.sync_rcts, CServiceConfig::GetInstance()->GetOperationPort());
	
	if( slave.SendRequestExecuteSyncToSlave( request, resultFd, nFileSize, strMessage ) == false )
	{
		// 전송 실패시
		_LOG( LERR, "%s", strMessage.c_str());
		close(resultFd);
		slave.Close();
		return -3;
	}
	_LOG( LDBG, "%s", strMessage.c_str());
	close(resultFd);
	slave.Close();
	return 1;
}
