#include "Logger.h"
#include "CcCollectdClientSocket.h"

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

#define LOG_PATH				"/user/service/logs"	// Log 경로


#define SERVER_ADDR				"222.122.152.5"		    // KT LogBackup Server IP
//#define SERVER_ADDR				"210.124.122.211"	    // LG U+ LogBackup Server IP 

#define SERVER_LISTEN_PORT	    13103					// cc_collectd Listen Port


int main(int argc, char * argv[])
{

	std::string strServerAddr = SERVER_ADDR;
	std::string strFullFileName;

	if( argc ==  2 )
	{
		strFullFileName = argv[1];
	}
	else if ( argc > 2 )
	{
		fprintf( stderr, "Too many parameter.\n");
		return EXIT_FAILURE;
	}
	else
	{
		// default
		strFullFileName = "/root/work/cc_collectd/interface/sample/test1.txt";
	}
		

	// 파일 Full 경로에서 파일명 추출 처리.
	std::string::size_type pos = strFullFileName.rfind( '/' );
	if( pos == std::string::npos )
	{
		// 찾지 못한 경우...
		fprintf( stderr, "File path is FULL PATH use. [%s]\n", strFullFileName.c_str() );
		return EXIT_FAILURE;
	}

	// 전송할 파일 정보
	std::string strTargetDir       = strFullFileName.substr( 0, pos );
	std::string strTragetFileName  = strFullFileName.substr( pos+1 );



	// 전송할 파일 관련 정보 추출.
	struct stat resultFileStat;

	if( stat( strFullFileName.c_str(), &resultFileStat ) != 0 )
	{
		int errorNum = errno;
		fprintf( stderr, "file[%s] stat check error.[%d][%s]\n", strFullFileName.c_str(), errorNum, strerror( errorNum ) );

		return EXIT_FAILURE;
	}

	// 파일 size 추출.
	unsigned long long uFileSize = resultFileStat.st_size;

	// fd open
	int fd = open(strFullFileName.c_str(), O_RDONLY );
	if( fd == -1 )
	{
		int errorNum = errno;
		fprintf( stderr, "file[%s] open fail.[%d][%s]\n", strFullFileName.c_str(), errorNum, strerror( errorNum ) );

		return EXIT_FAILURE;
	}
	
	
	// Log 처리용 객체 생성 및 초기화.
	if( CLogger::Init( PROG_NAME, LOG_PATH, LDBG ) == false )
	{
		close( fd );

		fprintf( stderr, "[error] Logger object created failed..");
		return EXIT_FAILURE;
	}


	// socket 생성 및 연결
	CCcCollectdClientSocket serverSocket;
	if( serverSocket.ConnectTarget( strServerAddr, SERVER_LISTEN_PORT ) == false )
	{
		// 접속 실패시
		close( fd );

		_LOG( LERR, "cc_collectd connect fail. [%s][%d]", strServerAddr.c_str(), SERVER_LISTEN_PORT );
		return EXIT_FAILURE;
	}

	std::string szErrorMessage;

	// Log 파일 존재 여부 확인
	unsigned long long uExistFileSize = 0;
	
	if( serverSocket.CheckFile( "collectd_client", strTragetFileName, uExistFileSize, szErrorMessage ) == false )
	{
		close( fd );

		_LOG( LERR, "cc_collectd exist check fail.[%s][%llu] -> [%s]", strTragetFileName.c_str(), uFileSize, szErrorMessage.c_str() );
		return EXIT_FAILURE;
	}
	else
	{
		_LOG( LDBG, "cc_collectd exist check OK.local[%s][%llu] remote[%llu]", strTragetFileName.c_str(), uFileSize, uExistFileSize );


		// Log 파일 크기가 다른 경우에만 전송 처리한다.
		if( uFileSize == uExistFileSize )
		{
			_LOG( LDBG, "cc_collectd same file exist. not send. local[%s][%llu] remote[%llu]", strTragetFileName.c_str(), uFileSize, uExistFileSize );
		}
		else
		{
			// 파일 크기가 다른 경우에만 전송 처리.
			// Log 파일 전송 처리
			if( serverSocket.SendFile( "collectd_client", strTragetFileName, fd, uFileSize, szErrorMessage ) == false )
			{
				close( fd );

				_LOG( LERR, "cc_collectd send fail.[%s][%llu] -> [%s]", strTragetFileName.c_str(), uFileSize, szErrorMessage.c_str() );
				return EXIT_FAILURE;
			}
			else
			{

				_LOG( LDBG, "cc_collectd send OK.[%s][%llu]", strTragetFileName.c_str(), uFileSize );
			}
		}
	}
	
	close( fd );

	return EXIT_SUCCESS;
}
