#include <iostream>
#include <sstream>
#include "EventDataManager.h"
#include <stdlib.h>
#include <algorithm>

#define REPEAT_ALLOW_TIME 60*60


// 생성자
CEventDataManager::CEventDataManager()
{
	pthread_mutex_init(&m_mutex, NULL);
}

// 소멸자
CEventDataManager::~CEventDataManager()
{
	pthread_mutex_destroy(&m_mutex);
}


bool CEventDataManager::Init(void)
{
	return true;
}


bool CEventDataManager::GetAllData(list<CEventData>& listRet)
{
	pthread_mutex_lock( &m_mutex );
	// SetCurrentData가 정상적으로 동작하였다면, m_Old.size()의 조건에 걸릴 수 없다.
	if ( m_Current.size() < 1 || m_Old.size() < 1 )
	{
		pthread_mutex_unlock( &m_mutex );
		_LOG(LINF, "Data have Nothing.");
		return false;
	}
	
	listRet = m_Current;
	pthread_mutex_unlock( &m_mutex );
	return true;
}

int CEventDataManager::GetLatestData( CEventData& resData )
{
	pthread_mutex_lock( &m_mutex );
	// SetCurrentData가 정상적으로 동작하였다면, m_Old.size()의 조건에 걸릴 수 없다.
	if ( m_Current.size() < 1 || m_Old.size() < 1 )
	{
		pthread_mutex_unlock( &m_mutex );
		_LOG(LINF, "Data have Nothing.");
		return -1;
	}

	
	if(  m_Old.back().m_evtTime ==  m_Current.back().m_evtTime )
	{	// ( 과거와 현재 최종 이벤트 시각이 동일하면 변화가 없는 것이다. )
		resData = m_Current.back();
		resData.m_szEventData = "NO EVENT";
		pthread_mutex_unlock( &m_mutex );
		return 0;
	}

	// 과거와 현재 최종 이벤트 시각이 다르면 이벤트가 추가된 것이다.
	resData = m_Current.back();
	pthread_mutex_unlock( &m_mutex );
	return 1;
}

bool CEventDataManager::SetCurrentData(list<CEventData>& listRet)
{
	pthread_mutex_lock( &m_mutex );
	if( listRet.empty() )
	{
		pthread_mutex_unlock( &m_mutex );
		_LOG(LINF, "EventData is empty.");
		return false;
	}

	// 들어온 데이터는 모두 시간순으로 정렬한다. (오름차순)
	// Old 데이터를 지운다.
	m_Old.clear();
	//현재 값이 비어있을 경우 (최초 실행으로 간주함)
	if( m_Current.empty() == true)
	{
		m_Old = listRet;
	}
	else
	{
		m_Old = m_Current;
	}
	m_Current = listRet;
	pthread_mutex_unlock( &m_mutex );
	return true;
}

bool CEventDataManager::GetSmsEvent(list<CEventData>& listRet)
{
	CEventData fetchedData;
	CEventData lastDataOfOld;
	list<CEventData> eventData = m_Current;
	list<CEventData> listFindTemp;

	pthread_mutex_lock( &m_mutex );

	if( m_Current.size() == 0 )
	{
		LOG(LERR, "List have No Data");
		pthread_mutex_unlock( &m_mutex );
		return false;
	}
	// 과거의 최신 데이터를 저장한다.
	m_SentOld = m_Old.back();
	// 현재 리스트의 뒤쪽(최신)부터 동일 데이터를 찾는다.
	// (데이터에 시간 값이 포함되어 있기 때문에 완전히 동일한 데이터는 없는 것으로 간주한다.)
	// (있을 경우 무시해도 되지 않을까?)
	
	listFindTemp.push_back(m_SentOld);
	// find_end를 사용하기 위해서 원소가 1개인 리스트를 생성한다.
	list<CEventData>::iterator it = find_end(m_Current.begin(), m_Current.end(), listFindTemp.begin(), listFindTemp.end());
	// 뒤쪽부터 원소가 1개인 리스트(listFindTemp)를 찾는다.
	// find_end()는 집합에 속하는 부분집합을 찾는다.

	
	// 찾아낸 데이터의 뒤쪽 부분은 신규 데이터이다.
	if( it == m_Current.end() )
	{	// end()와 같다면, 끝까지 찾지 못한 것을 의미한다. (NOT FOUND)
		// 찾지 못한 것은 전체가 다 새로운 것이다.
		_LOG(LINF, "List has NEW Event perfectly.");
		it = m_Current.begin();
	}
	else
	{	// 찾아낸 데이터의 다음 데이터를 가리키도록 한다.
		++it;
	}

	// 신규 데이터 목록 중 앞쪽(오래된)부터 중복된 데이터인지를 검사한다.
	for( ; it != m_Current.end(); it++)
	{
		if( it->m_szEventData == m_SentOld.m_szEventData 
				&& it->m_evtTime - m_SentOld.m_evtTime  < REPEAT_ALLOW_TIME 
				&& it->m_evtTime - m_SentOld.m_evtTime  >= 0 )
		{	// 내용이 중복되고 마지막 이벤트로부터 1시간 미만 차이나면?
			// BUG: Areca bug로 시간이 역순할 수 있다. REPEAT_ALLOW_TIME보다 작은 음수 값이 나오게 되면 무시하면 안된다.
			_LOG(LINF, "There is Repeted Event.[%s]",it->m_szEventData.c_str());
			// 중복 되면 버린다.(과거 데이터를 우선한다)
			continue;
		}

		// 중복 데이터가 아니면 결과에 추가 한다.(SMS발송 대상)
		listRet.push_back(*it);
		m_SentOld = *it;
		_LOG(LDBG, "ADD : [%lu::%s]", it->m_evtTime, it->m_szEventData.c_str());
	}
	// SMS발송 대상이 없을 경우 디버깅 로그만 남긴다.
	if( listRet.size() == 0 )
	{
		LOG(LDBG, "There is No New Event.");
	}
	pthread_mutex_unlock( &m_mutex );
	return true;
}
