/***************************************************************************
                RC Contents Move Tool
                -----------------------------------------
	begin      : 2012/05/13
	copyright  : (C) 2011 SolutionBox Inc.
	author     : Service 1 Team
	email      : svc1@solbox.com
	version    : 3.1.0

    CopyRight(C) 2011 SolutionBox Inc. All Rights reserved.
    Redistribution and use in source and binary forms, with or with out
    modification, are not permitted in outside of SolutionBox Inc.
***************************************************************************/
#ifndef __SERVICE_SYNC_H__
#define __SERVICE_SYNC_H__

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>


#include <iostream>
#include <vector>
#include <map>
#include <sstream>
#include <cctype>

using namespace std;

// -m type
#define MODE_SYNC	"sync"
#define MODE_COPY	"copy"
#define MODE_MOVE	"move"

// sync file flag
#define	FLAG_SYNC	"SYNC"
#define	FLAG_NSYNC  "NSYNC"
#define	FLAG_DEL	"DEL"
#define	FLAG_COPY	"COPY"
#define	FLAG_MOVE	"MOVE"
#define	FLAG_RECHK	"RECHK"

// resource_type
#define  TYPE_FILE	"0"
#define  TYPE_DIR	"1"

#define SPACES		" \t\r\n"

class databaseinfo
{
public:
	databaseinfo() {}
	~databaseinfo() {}
public:
	string	m_hostaddr;
	int		m_port;
	string	m_dbname;
	string	m_user;
	string	m_pw;
};

// sync file formate file
// flag|uri|filename_hash|resource_type|get_content_length|file_lastmodified|deleted_yn|host_name|creation_date|get_content_type|src_uri|slave_tran_id
class SYNCFILE_FIELD
{
public:
	// SYNCFILE_FIELD::flag
	// - SYCN : 동기화 필요
	// - NSYCN: 논리적 동기화 필요
	// - DEL  : 삭제 필요
	// - COPY : 복사된 파일임
	// - MOVE : 이동된 파일임
	// - RECHK: 다시 검증

	enum FIELD
	{
		flag = 0, uri, filename_hash, resource_type, get_content_length,
		file_lastmodified, deleted_yn, host_name, creation_date, get_content_type,
		src_uri, slave_tran_id, uri_ignore_case,
		MAX_FILED
	};
};

class CURRENT_FIELD
{
public:
	enum FIELD
	{
		uri = 0, filename_hash, resource_type, get_content_length, get_lastmodified,
		file_lastmodified, deleted_yn, host_name, creation_date, get_content_type,
		MAX_FILED
	};
};

namespace JOB_TYPE
{
	enum JOB_TYPE
	{
		UNSET = 0,
		COPY = 1,
		MOVE = 2
	};
};

typedef vector< vector<string> > CSyncData;

#ifdef __cplusplus
extern "C" {
#endif

	// Split string function
	// bUseEmpty값이 true면 delimiter의 갯수에 따라 results.size()의 숫자도 맞추기 위한 옵션
	void StringSplit(string str, string delim, vector<string> &results, bool bUseEmpty = false);

	// delim 의 갯수를 리턴한다.
	int StringCount(string str, string delim);

	// microsecond now time
	long long longtime_now();

	// string now time
	string strtime_now();

	// string to time_t
	time_t str2time_t(string strtime);

	// string to microsecond
	long long str2longtime(string strtime);

	// 파일의 크기를 가져온다. 파일이 없을 경우 -1 리턴
	long GetFileSize(const char* path);

	// command 명령어 실행 화면 출력 결과를 string으로 리턴
	string getCommand(string cmd);

	// trim string right
	inline string trim_right(const string & s, const string & t = SPACES)
	{
		string d (s);
		string::size_type i (d.find_last_not_of (t));
		if (i == string::npos)
			return "";
		else
			return d.erase(d.find_last_not_of (t) + 1) ;
	}

	// trim string left
	inline string trim_left(const string & s, const string & t = SPACES)
	{
		string d (s);
		return d.erase(0, s.find_first_not_of (t)) ;
	}

	// trim string left and right
	inline string trim(const string & s, const string & t = SPACES)
	{
		string d (s);
		return trim_left(trim_right (d, t), t) ;
	}

	string StringReplace(const string& source, const string search, const string replacement);

	void solusleep(unsigned long usec);

#ifdef __cplusplus
}
#endif

#ifdef _DEBUG

#define COUT(level, levelkey, msg) \
	cout << "[PID:"<<  getpid() <<"-" << pthread_self()  <<"] ["<< #levelkey << "] "  << msg.str() << endl;

#define  CERR(level, levelkey, msg) \
	cerr << "[PID:"<<  getpid() <<"-" << pthread_self()  <<"] ["<< #levelkey << "] "  << msg.str() << endl;

#else // _DEBUG

#define COUT(level, levelkey, msg) \
	if(level < LDBG) \
		cout << "[PID:"<<  getpid() <<"-" << pthread_self()  <<"] ["<< #levelkey << "] "  << msg.str() << endl;
#define  CERR(level, levelkey, msg) \
	if(level < LDBG) \
		cerr << "[PID:"<<  getpid() <<"-" << pthread_self()  <<"] ["<< #levelkey << "] "  << msg.str() << endl;

#endif // _DEBUG

#define  _LOGACOUT(level, msg) \
	_LOG(level,"[PID:%d-%d] %s", getpid(), pthread_self(), msg.str().c_str());\
	COUT(level, #level,msg);\
	msg.str("");

#define  LOGACOUT(level, msg) \
	LOG(level,"[PID:%d-%d] %s", getpid(), pthread_self(), msg.str().c_str());\
	COUT(level, #level, msg);\
	msg.str("");

#define  _LOGACERR(level, msg) \
	_LOG(level,"[PID:%d-%d] %s", getpid(), pthread_self(), msg.str().c_str());\
	CERR(level, #level, msg);\
	msg.str("");

#define  LOGACERR(level, msg) \
	LOG(level,"[PID:%d-%d] %s", getpid(), pthread_self(), msg.str().c_str());\
	CERR(level, #level, msg);\
	msg.str("");

// dummy
#define  REPORT_SUCCESS(format, ...)
#define  REPORT_FAIL(format, ...)
#define  REPORT_WARNING(format, ...)
#define  REPORT_NOTICE(format, ...)

#endif // __SERVICE_SYNC_H__
