#include "SyncList.h"
#include "ServiceConfig.h"
#include "Database.h"
#include "DBConnPool.h"
#include "Logger.h"
#include "ReportLog.h"

#include <unistd.h>
#include <string.h>

#define  SYNC_FILE_PATH		"/user/service/_sync"

// CSyncInfo class
CSyncInfo::CSyncInfo()
{
}

CSyncInfo::~CSyncInfo()
{
}

void CSyncInfo::UnlinkFile()
{
	unlink(file_master_name.c_str());
	unlink(file_slave_name.c_str());
	unlink(file_diff_name.c_str());
	
	if (sync_type < SYNC_TYPE::CHK_ONLY )
		unlink(file_sync_name.c_str());
}

// CSyncLinst class
CSyncList::CSyncList()
{
}

CSyncList::~CSyncList()
{
	m_list.clear();
}

bool CSyncList::CreateList(CReqMasterData & d)
{
	// Sync Info from RCDB 
	DataBase *db = CMasterDBPool::getInstance()->GetConnFromPool();

	if (!db)
	{
		LOG(LERR, "Failed GetDB.");
		return false;
	}

	ostringstream sql;

	sql << "SELECT";
	sql << " S.sp_svc_tran_id, S.master_yn, S.linked_sp_svc_tran_id, S.linked_rcts, P.sp_svc_tran_id, P.uri_ignore_case ";
	sql << " FROM t_sms_sp_svc_product_sync S ";
	sql << " LEFT JOIN t_sms_sp_svc_product P ON(S.sp_svc_tran_id = P.sp_svc_tran_id) ";

	if (d.one_service.empty())//d.service_list.empty())
	{
		// All
	}
	else
	{
		string s = d.one_service;
		// part
		/*
		for (list<string>::iterator list_iter = d.service_list.begin();
			list_iter != d.service_list.end(); list_iter++)
		{
			if (list_iter != d.service_list.begin())
				s += ",";
			s += *list_iter;
		}
		*/
		sql << " WHERE P.sp_svc_tran_id IN (" << s << ")";
	}

	db->PgDoExec((char*)sql.str().c_str());

	if (db->PgResult(DataBase::NOT_CLEAR) < 0)
	{

		LOG(LERR, " Failed Get Sync List. %s", db->GetErrorMessage().c_str());
		db->PgClear();
		CMasterDBPool::getInstance()->ReleaseConnToPool(db, false);
		return false;
	}

	for (int i = 0; i < db->GetNoTuples(); ++i)
	{
		CSyncInfo t;
		if (strlen(db->GetValue(i, 4)) <= 0)
		{
			//LOG(LNOT, "Not Found Service.[tran_id :%s]", db->GetValue(i, 0));
			
			CReportLog rlog;

			if (rlog.Init(CServiceConfig::GetInstance()->GetLogPath()))
			{
				rlog.Write("NOT", "[%s] [Not Found Sync Service in Product Table.[tran_id :%s]]", PROG_NAME, db->GetValue(i, 0));
			}

			continue;
		}
		
		// master 
		if (strcmp(db->GetValue(i, 1), "Y") == 0)
		{
			t.uri_ignore_case = db->GetValue(i, 5);
			
			t.start_time	= d.start_time;
			t.end_time		= d.end_time;
			t.sync_type		= d.sync_type;

			t.sync_master	= db->GetValue(i, 0);
			t.sync_slave	= db->GetValue(i, 2);
			t.sync_rcts		= db->GetValue(i, 3);

			GenFileName(t);
			
			m_list.push_back(t);
		}
	}

	db->PgClear();
	CMasterDBPool::getInstance()->ReleaseConnToPool(db);

	if (m_list.empty())
	{
		LOG(LWAR, "Empty Sync List.");
		return false;
	}

	return true;
}

bool CSyncList::CreateList(CReqSlaveData & d)
{
	CSyncInfo i;
	CreateList((CReqServiceData*)&d, i);

	i.sync_master = d.master;
	i.sync_slave = d.slave;
	
	GenFileName(i);
	
	m_list.push_back(i);

	return true;
}

bool CSyncList::CreateList(CReqSyncData & d)
{
	CSyncInfo i;
	CreateList((CReqServiceData*)&d, i);

	i.sync_master = d.master;
	i.sync_slave = d.slave;

	GenFileName(i);

	m_list.push_back(i);

	return true;
}

CSyncInfo CSyncList::Pop()
{
	CSyncInfo r = m_list.front();
	m_list.pop_front();
	return r;
}

bool CSyncList::CreateList(const CReqServiceData * d,  CSyncInfo & i)
{
	i.start_time = d->start_time;
	i.end_time = d->end_time;
	i.sync_type = d->sync_type;
	return true;
}

void CSyncList::GenFileName(CSyncInfo & i)
{
	ostringstream tmp;
	//Source file
	//	- diff 대상 파일
	//	- source_(master)tran_id_starttime_endtime_TreadID.(master / slave)
	tmp.str("");
	tmp << SYNC_FILE_PATH << "/source_" << i.sync_master << "_" << i.sync_slave << i.sync_rcts << "_";
	tmp << i.start_time << "_" << i.end_time << "_" << pthread_self() << ".master";
	i.file_master_name = tmp.str();

	tmp.str("");
	tmp << SYNC_FILE_PATH << "/source_" << i.sync_master << "_" << i.sync_slave << i.sync_rcts << "_";
	tmp << i.start_time << "_" << i.end_time << "_" << pthread_self() << ".slave";
	i.file_slave_name = tmp.str();

	//Diff file
	//	- Source data 비교한 결과
	//	- diff_(master)tran_id_starttime_endtime_TreadID
	tmp.str("");
	tmp << SYNC_FILE_PATH << "/diff_" << i.sync_master << "_" << i.sync_slave << i.sync_rcts << "_";
	tmp << i.start_time << "_" << i.end_time << "_" << pthread_self() ;
	i.file_diff_name = tmp.str();

	//Sync file
	//- 동기(이관) 대상 파일
	//- sync_(master)tran_id_starttime_endtime_TreadID
	tmp.str("");
	tmp << SYNC_FILE_PATH << "/sync_" << i.sync_master << "_" << i.sync_slave << i.sync_rcts << "_";
	tmp << i.start_time << "_" << i.end_time << "_" << pthread_self();
	i.file_sync_name = tmp.str();
}
