//********************************************************************************
//	ファイル名：DailyLogManager.cpp													
//	用　　　途：ログ管理クラス定義											
//	備　　　考：															
//	履　　　歴：
//********************************************************************************
/****************************
*	 コンパイル環境設定		*
****************************/
#include "stdafx.h"
/****************************
*	インクルードファイル	*
****************************/
#include "DailyLogManager.h"
#include "System.h"
#include "Tools.h"
/****************************
*		 マクロ定数			*
****************************/

/****************************
*		 構造体定義			*
****************************/
/****************************
*		 クラス定義			*
****************************/
/****************************
*		 関数　宣言			*
****************************/
/****************************
*		 変数　宣言			*
****************************/

//********************************************************************************
//*	関数名：CDailyLog									
//*	用　途：デフォルトコンストラクタ											
//*	引き数：																	
//*	戻り値：
//*	備　考：
//********************************************************************************
CDailyLog::CDailyLog()
{
	memset(&m_tParamDailyLog , 0 , sizeof(m_tParamDailyLog));
	m_uLogID = 0;

	m_nNofFileBuf = 200;
}


//********************************************************************************
//*	関数名：~CDailyLog							
//*	用　途：デストラクタ						
//*	引き数：									
//*	戻り値：							
//*	備　考：							
//********************************************************************************
CDailyLog::~CDailyLog()
{
	FileFlash();
}


//********************************************************************************
//*	関数名：SetParam										
//*	用　途：環境設定									
//*	引き数：パラメータ構造体							
//*	戻り値：設定成功でTRUE、失敗でFALSE		
//*	備　考：												
//********************************************************************************
BOOL CDailyLog::SetParam(tagParamDailyLog& tParamDailyLog)
{

	m_tParamDailyLog = tParamDailyLog;



	m_Log.SetConfig(FALSE, FALSE, m_tParamDailyLog.bEnable , 10 , TRUE);	/* 日付挿入なし、自動改行なし、有効 、10MBで削除、旧ファイルはリネームして残す*/

	m_strFileName	= MakeFileName();


	/***** ディスク残量が一定以下の場合は作成しない *****/
	//DISK_INFO	tInf;
	//GetDiskSize((LPCTSTR)m_strBasePath, &tInf);

	//if ( tInf.uAvailable < GigaBytes(m_nRestSize) ) return FALSE;


	TCHAR szTmp[_MAX_PATH];
	_tcscpy_s(szTmp , _MAX_PATH , m_strFileName);
	m_Log.CreateFile(szTmp , FALSE);

	::PostMessage( m_tParamDailyLog.hDspMessageWnd , m_tParamDailyLog.nDspMessageID , (WPARAM)m_uLogID, 0 ) ;	//表示更新メッセージ

	return TRUE;
}


//********************************************************************************
//*	関数名：SetNofFileBuf										
//*	用　途：環境設定									
//*	引き数：パラメータ							
//*	戻り値：設定成功でTRUE、失敗でFALSE		
//*	備　考：												
//********************************************************************************
BOOL CDailyLog::SetNofFileBuf(INT32 nNofFlieBuf)
{
	m_nNofFileBuf = nNofFlieBuf;
	return TRUE;

}


//********************************************************************************
//*	関数名：Print											
//*	用　途：ログに１データ出力する							
//*	引き数：データ											
//*	戻り値：
//*	備　考：
//********************************************************************************
BOOL CDailyLog::Print(TCHAR *szFmt, ...)
{

	CString		strPrint ;		// 結果文字列
	LPTSTR		psz      ;		// 文字列
	va_list		argList  ;		// 可変長引数リスト

	va_start( argList, szFmt ) ;
	psz = strPrint.GetBufferSetLength( LENGTH_DAILYLOG ) ;
	_vsntprintf_s( psz, LENGTH_DAILYLOG ,LENGTH_DAILYLOG, szFmt, argList ) ;
	strPrint.ReleaseBuffer() ;
	va_end( argList );
	
	return Print(strPrint);
}


//********************************************************************************
//*	関数名：Print											
//*	用　途：ログに１データ出力する							
//*	引き数：データ											
//*	戻り値：
//*	備　考：
//********************************************************************************
BOOL CDailyLog::Print(CString &str)
{
	BOOL bRet = TRUE;

	m_cs.Lock();

	m_strPrefix = GetLogPrefix( );
	//時間追加
	m_strPrefix += str;

	//ファイル保存用バッファに記録
	if(m_saFilePrints.GetCount() < m_nNofFileBuf){
		m_saFilePrints.AddTail( m_strPrefix ) ;
	}else{
		bRet = FALSE;
	}

	//画面表示用用バッファに記録
	if( m_saDspPrints.GetCount() < 200){
		m_saDspPrints.AddTail( m_strPrefix ) ;

		::PostMessage( m_tParamDailyLog.hDspMessageWnd , m_tParamDailyLog.nDspMessageID , (WPARAM)m_uLogID , 0 ) ;	//表示更新メッセージ
		
	}

	m_cs.Unlock();
		

	return bRet;
}


//********************************************************************************
//*	関数名：FileFlash											
//*	用　途：ファイル保存用バッファのデータをファイルに書き出し	
//*	引き数：
//*	戻り値：
//*	備　考：
//********************************************************************************
void CDailyLog::FileFlash()
{
	CString		strPrint = _T("");


	m_strFileName	= MakeFileName();

	//ファイルが見つからない場合新規作成
	if(m_FileFinder.FindFile(m_strFileName) == FALSE){

		/***** ディスク残量が一定以下の場合は作成しない *****/
		DISK_INFO	tInf;
		GetDiskSize(m_tParamDailyLog.szPath , &tInf);
		if ( tInf.uAvailable < GigaBytes(m_tParamDailyLog.nRestSize) ) {
			return;
		}

		TCHAR szTmp[_MAX_PATH];
		_tcscpy_s(szTmp , _MAX_PATH , m_strFileName);
		m_Log.CreateFile(szTmp , TRUE);

	}

	//バッファから出力文字列を取り出す間だけロック
	m_cs.Lock();

	// データがなくなるまで書き出し
	while( m_saFilePrints.IsEmpty() == FALSE ) { 
		strPrint += m_saFilePrints.RemoveHead() ;
		strPrint += _T("\n") ;
	}

	m_cs.Unlock();


	//ファイルに書き込み
	if(strPrint.IsEmpty() == FALSE) m_Log.Print(strPrint);


}




//********************************************************************************
//*	関数名：MakeFileName								
//*	用　途：ファイル名の作成							
//*	引き数：ファイル名格納場所、アプリケーションデータ	
//*	戻り値：ファイル名									
//*	備　考：												
//********************************************************************************
CString CDailyLog::MakeFileName()
{
	CString strFileName ;
	CString strFileTime ;

	// 日時の取得
	SYSTEMTIME tSystemTime = { 0 };
	::GetLocalTime(&tSystemTime);

	strFileTime.Format(_T("%04d_%02d_%02d"),
				tSystemTime.wYear,
				tSystemTime.wMonth,
				tSystemTime.wDay
				);

	strFileName = m_tParamDailyLog.szPath ;
	strFileName += _T("\\");
	strFileName += m_tParamDailyLog.szFileName;
	strFileName += _T("_") + strFileTime + _T(".log");

	return strFileName;
}


//********************************************************************************
//*	関数名：GetLogPrefix										
//*	用　途：出力するログの先頭に付加する文字列を取得します。	
//*	引き数：													
//*	戻り値：													
//*	備　考：
//********************************************************************************
CString CDailyLog::GetLogPrefix()
{
	CString strPrefix ;

	// 日時の取得
	SYSTEMTIME tSystemTime = { 0 };
	::GetLocalTime(&tSystemTime);


	strPrefix.Format(_T("%04d/%02d/%02d %02d:%02d:%02d.%03d     "),
				tSystemTime.wYear,
				tSystemTime.wMonth,
				tSystemTime.wDay,
				tSystemTime.wHour,
				tSystemTime.wMinute,
				tSystemTime.wSecond,
				tSystemTime.wMilliseconds);

	return strPrefix;

}





//********************************************************************************
//*	関数名：GetDspPrints					
//*	用　途：表示用ログ文字列取得			
//*	引き数：								
//*	戻り値：								
//*	備　考：
//********************************************************************************
CString CDailyLog::GetDspPrints()
{
	CString str ;

	m_cs.Lock();
	
	if(m_saDspPrints.IsEmpty() == FALSE){
		str =  m_saDspPrints.RemoveHead() ;
	}

	m_cs.Unlock();

	return str;
}



//********************************************************************************
//*	関数名：DeleteDeadLineFile									
//*	用　途：期限前のファイルを削除								
//*	引き数：
//*	戻り値：削除成功でＴＲＵＥ、失敗でＦＡＬＳＥ				
//*	備　考：フォルダは削除しない(サブフォルダも)				
//*			隠しファイルも削除するが権限が無い場合は失敗する。	
//********************************************************************************
BOOL CDailyLog::DeleteDeadLineFile()
{
	CString strPath = m_tParamDailyLog.szPath;

	//空白の場合は無視
	strPath.Remove(_T(' '));
	//strPath.Remove(_T('　'));
	if(strPath.IsEmpty() == TRUE){
		return FALSE;
	}

	return DeleteDeadLineFile(strPath , m_tParamDailyLog.nDaysOfDeadLine);
}

//********************************************************************************
//*	関数名：DeleteDeadLineFile									
//*	用　途：期限前のファイルを削除								
//*	引き数：削除したいファイルの存在するパス、期日（日）
//*	戻り値：削除成功でＴＲＵＥ、失敗でＦＡＬＳＥ				
//*	備　考：フォルダは削除しない(サブフォルダも)				
//*			隠しファイルも削除するが権限が無い場合は失敗する。	
//********************************************************************************
BOOL CDailyLog::DeleteDeadLineFile(CString &strPath, INT32 nDaysOfDeadLine)
{
	CFileFind	find;
	CTime		CurrentTime, DeadLine, TimeStamp;
	CString		str, strFind, strDeleteFile;
	BOOL		bFind;

	if ( nDaysOfDeadLine <= 0 ) return FALSE; 

	/***** 初期化 *****/
	CurrentTime	= CTime::GetTickCount();
	DeadLine	= CurrentTime - CTimeSpan(nDaysOfDeadLine, 0, 0, 0);


	strFind	= strPath + _T("\\*.*");

	bFind	= find.FindFile(strFind); 

	while(bFind)
	{
		bFind = find.FindNextFile();
		if( find.IsDots() ) continue;

		strDeleteFile = find.GetFilePath();
		find.GetLastWriteTime(TimeStamp);

		if (find.IsDirectory())
		{
			DeleteDeadLineFile(strDeleteFile , nDaysOfDeadLine);
			::RemoveDirectory(strDeleteFile);
		}
		else
		{
			if( TimeStamp <= DeadLine )
			{
				::SetFileAttributes(strDeleteFile, FILE_ATTRIBUTE_NORMAL);
				::DeleteFile(strDeleteFile);
			}
		}
	};

	find.Close();

	return TRUE;
}














//********************************************************************************
//*	関数名：CDailyLogManager																
//*	用　途：デフォルトコンストラクタ												
//*	引き数：																		
//*	戻り値：
//*	備　考：
//********************************************************************************
CDailyLogManager::CDailyLogManager()  : CThread()
{

	m_nSleepCntFlash = 0;
	m_nSleepCntDelete = 0;

}


//********************************************************************************
//*	関数名：~CDailyLogManager			
//*	用　途：デストラクタ		
//*	引き数：					
//*	戻り値：				
//*	備　考：
//********************************************************************************
CDailyLogManager::~CDailyLogManager()
{
	End();

	//ログクラスを破棄
	m_cs.Lock();

	for(int i=0 ; i<m_arDailyLog.GetCount() ; i++){
		if(m_arDailyLog[i]) delete m_arDailyLog[i];
	}
	m_arDailyLog.RemoveAll();

	m_cs.Unlock();

}






//********************************************************************************
//*	関数名：Initialize
//*	用　途：初期化
//*	引き数：ファイル書き込み間隔[msec] , ファイル削除確認間隔[msec]
//*	戻り値：
//*	備　考：
//********************************************************************************
BOOL CDailyLogManager::Initialize(int nItvFlash , int nItvDelete)
{

	m_nItvFlash = nItvFlash;
	m_nItvDelete = nItvDelete;

	Begin();

	return FALSE;
}

//********************************************************************************
//*	関数名：AddDailyLog
//*	用　途：新規ログの追加
//*	引き数：ログパラメータ
//*	戻り値：ログID
//*	備　考：
//********************************************************************************
int CDailyLogManager::AddDailyLog(tagParamDailyLog& tParamDailyLog)
{
	CSingleLock Lock( &m_cs, TRUE ) ;		// 関数内セマフォロック

	//新規作成
	CDailyLog*	pDailyLog = new CDailyLog;

	//パラメータセット
	pDailyLog->SetParam(tParamDailyLog);

	//配列に追加
	int nLogID = (int)m_arDailyLog.Add(pDailyLog);

	//ログIDセット
	m_arDailyLog[nLogID]->SetID(nLogID);

	return nLogID;
}

//********************************************************************************
//*	関数名：Main									
//*	用　途：スレッド処理実体						
//*	引き数：										
//*	戻り値：処理終了時はTRUE、継続時はFALSE
//*	備　考：
//********************************************************************************
BOOL CDailyLogManager::Main()
{

	//監視間隔待ち
	Sleep(ITV_CHK);
	m_nSleepCntFlash += ITV_CHK;
	m_nSleepCntDelete += ITV_CHK;


	//ファイル書き込み
	if(m_nSleepCntFlash > m_nItvFlash){
		m_nSleepCntFlash = 0;

		for(int i=0 ; i<m_arDailyLog.GetCount() ; i++){
			m_arDailyLog[i]->FileFlash();
		}
	}


	//ファイル削除確認
	if(m_nSleepCntDelete > m_nItvDelete){
		m_nSleepCntDelete = 0;

		for(int i=0 ; i<m_arDailyLog.GetCount() ; i++){
			m_arDailyLog[i]->DeleteDeadLineFile();
		}
	}

	return FALSE;
}

//********************************************************************************
//*	関数名：SetParam											
//*	用　途：パラメータ更新							
//*	引き数：ログID , パラメータ											
//*	戻り値：
//*	備　考：
//********************************************************************************
BOOL CDailyLogManager::SetParam(UINT uLogID , tagParamDailyLog	tParamDailyLog)
{
	if(uLogID < (UINT)m_arDailyLog.GetCount() ){
		return m_arDailyLog[uLogID]->SetParam(tParamDailyLog);
	}else{
		return FALSE;
	}
}


//********************************************************************************
//*	関数名：SetNofFileBuf											
//*	用　途：パラメータ更新							
//*	引き数：ログID , パラメータ											
//*	戻り値：
//*	備　考：
//********************************************************************************
BOOL CDailyLogManager::SetNofFileBuf(UINT uLogID, INT32 nNofFlieBuf)
{
	if(uLogID < (UINT)m_arDailyLog.GetCount() ){
		return m_arDailyLog[uLogID]->SetNofFileBuf(nNofFlieBuf);
	}else{
		return FALSE;
	}
}


//********************************************************************************
//*	関数名：GetParam											
//*	用　途：パラメータ取得						
//*	引き数：ログID , パラメータ											
//*	戻り値：
//*	備　考：
//********************************************************************************
BOOL CDailyLogManager::GetParam(UINT uLogID , tagParamDailyLog* tpParamDailyLog)
{
	if(tpParamDailyLog == NULL)return FALSE;

	if(uLogID < (UINT)m_arDailyLog.GetCount() ){
		*tpParamDailyLog  = m_arDailyLog[uLogID]->GetParam();
		return TRUE;
	}else{
		return FALSE;
	}
}



//********************************************************************************
//*	関数名：Print											
//*	用　途：ログに１データ出力する							
//*	引き数：ログID , データ											
//*	戻り値：
//*	備　考：
//********************************************************************************
BOOL CDailyLogManager::Print(UINT uLogID , TCHAR *szFmt, ...)
{

	CString		strPrint ;		// 結果文字列
	LPTSTR		psz      ;		// 文字列
	va_list		argList  ;		// 可変長引数リスト

	va_start( argList, szFmt ) ;
	psz = strPrint.GetBufferSetLength( LENGTH_DAILYLOG ) ;
	_vsntprintf_s( psz, LENGTH_DAILYLOG ,LENGTH_DAILYLOG, szFmt, argList ) ;
	strPrint.ReleaseBuffer() ;
	va_end( argList );
	
	return Print(uLogID , strPrint);
}


//********************************************************************************
//*	関数名：Print											
//*	用　途：ログに１データ出力する							
//*	引き数：ログID , データ											
//*	戻り値：
//*	備　考：
//********************************************************************************
BOOL CDailyLogManager::Print(UINT uLogID , CString &str)
{
	if(uLogID < (UINT)m_arDailyLog.GetCount() ){
		return m_arDailyLog[uLogID]->Print(str);
	}else{
		return FALSE;
	}
}

//********************************************************************************
//*	関数名：GetDspPrints											
//*	用　途：表示用ログ文字列取得							
//*	引き数：ログID								
//*	戻り値：
//*	備　考：
//********************************************************************************
CString CDailyLogManager::GetDspPrints(UINT uLogID )
{
	if(uLogID < (UINT)m_arDailyLog.GetCount() ){
		return m_arDailyLog[uLogID]->GetDspPrints();
	}else{
		return _T("");
	}
}
