#include "MakeSyncFile.h"
#include "ExecCall.h"
#include "WorkPool.h"
#include "Logger.h"
#include "Util.h"
#include <fstream>

#define  WORK_WAIT		1000000 // microsecond

static int worknotifyfn(void *object, short success)
{
	CMakeSyncFile* o = reinterpret_cast<CMakeSyncFile *>(object);

	return o->WorkNotify(success);
}

CMakeSyncFile::CMakeSyncFile(CSyncInfo &info)
	: m_info(info), m_stop(false)
{
	pthread_mutex_init(&m_notifymutex, NULL);
}

CMakeSyncFile::~CMakeSyncFile()
{
	m_stop = true;
	pthread_mutex_destroy(&m_notifymutex);
}

bool CMakeSyncFile::MakeSyncFile()
{
	CExecCall diff(m_info);

	// diff
	if (diff.Call(CExecCall::DIFF_SCRIPT) != 0)
	{
		LOG(LERR, "diff data file make failed.[%s]", m_info.file_diff_name.c_str());
		return false;
	}
		
	// read diff file 
	m_status.m_diff = diff.GetFileLine(m_info.file_diff_name.c_str());
	if (m_status.m_diff < 0)
	{
		LOG(LERR, "Failed diff command call");
		return false;
	}
	
	ifstream difffile;
	try {
		difffile.open(m_info.file_diff_name.c_str());
		if (!difffile.is_open())
		{
			LOG(LWAR, "No difference.[%s=>%s:%s~%s]",
				m_info.sync_master.c_str(), m_info.sync_slave.c_str(),
				m_info.start_time.c_str(), m_info.end_time.c_str());
			return true;
		}
	}
	catch (ios_base::failure& e)
	{
		LOG(LERR, "diff data file open error.[%s]", m_info.file_diff_name.c_str());
		return false;
	}

	string line;
	while (!difffile.eof())
	{
		getline(difffile, line);
		if (line.empty() == true || line == "\r")
		{
#ifdef _DEBUG
			cout << "diff data read : empty or linefeed" << line << endl;
#endif // _DEBUG
			continue;
		}

		CWork *w = CWorkPool::getInstance()->GetWorkPool();
		if (w != NULL)
		{
			++m_status.m_work;
			// validation
			w->run(m_info, line, worknotifyfn, this);
		}
		else
		{
			++m_status.m_launcherfail;
			LOG(LERR, "Get Work Pool error.[%s]", line.c_str());
		}
	}

	difffile.close();

	// 마지막 라인에 캐리지 리턴 없는 경우 파일을 실제 읽었을 때보다 
	// 한라인 작은 수를 wc -l 에서 출력되어 작업이 완료되지 않는 것을
	// 막기 위해서 work가 diff 값보다 클 때 diff 값을 work 값으로 보정
	if (m_status.m_diff < m_status.m_work)
		m_status.m_diff = m_status.m_work;

	// end of validation
	do
	{
		if (m_status.m_diff ==
			(m_status.m_error + m_status.m_success + m_status.m_launcherfail))
		{
			LOG(LDEV1, "work end of validation");
			m_stop = true;
			break;
		}

		LOG(LDEV1, "working of validation.........");

		solusleep(WORK_WAIT);
	} while (!m_stop);

	return true;
}

int CMakeSyncFile::WorkNotify(short success)
{
	pthread_mutex_lock(&m_notifymutex);

	if (success == 0)
	{
		++m_status.m_success;
	}
	else
	{
		++m_status.m_error;
	}

	pthread_mutex_unlock(&m_notifymutex);
	return 0;
}
