//****************
//
//****************


#pragma once

#include "windows.h"
#include "stdio.h"
#include "time.h"
#include "assert.h"

class CLogFile
{
public:
	CLogFile::CLogFile(char* pszFileName = NULL)
	{
		m_pszFileName = NULL;
		m_hFile = INVALID_HANDLE_VALUE;
		::InitializeCriticalSection(&m_csLock);

		time_t now;
		time(&now);
		tm* pt = localtime(&now);

		if(pszFileName == NULL)
		{
			m_pszFileName = new char[64];
			sprintf(m_pszFileName, "%d%02d%02d%02d%02d%02d.txt", pt->tm_year + 1900, pt->tm_mon, pt->tm_mday, pt->tm_mon, pt->tm_min, pt->tm_sec);
		}
		else
		{
			SetFileName(pszFileName);
		}
	}

	virtual ~CLogFile(void)
	{
		::DeleteCriticalSection(&m_csLock);
		Close();

		if(m_pszFileName)
			delete[] m_pszFileName;
	}

	const char* GetFileName(void)
	{
		return m_pszFileName;
	}

	void SetFileName(const char* pszFileName)
	{
		assert(pszFileName);

		if(m_pszFileName)
			delete[] m_pszFileName;

		Close();

		m_pszFileName = new char[strlen(pszFileName) + 1];
		assert(m_pszFileName);
		strcpy(m_pszFileName, pszFileName);
	}

	bool IsOpen(void)
	{
		return m_hFile != INVALID_HANDLE_VALUE;
	}

	void Close(void)
	{
		if(IsOpen())
		{
			CloseHandle(m_hFile);
			m_hFile = INVALID_HANDLE_VALUE;
		}
	}

	// 追加日志内容
	void Log(LPCVOID lpBuffer, DWORD dwLength, bool bRecordTime = false)
	{
		assert(lpBuffer);

		__try
		{
			Lock();

			if(OpenFile())
			{
				WriteLog(lpBuffer, dwLength, bRecordTime);
			}
		}
		__finally
		{
			Unlock();
		}
	}

	void Log(const char* pszText, bool bRecordTime = false)
	{
		Log(pszText, strlen(pszText), bRecordTime);
	}

protected:
	CRITICAL_SECTION m_csLock;
	char* m_pszFileName;
	HANDLE m_hFile;

protected:
	bool OpenFile(void)
	{
		if(IsOpen())
			return true;

		if(!m_pszFileName)
			return false;

		m_hFile = CreateFileA(m_pszFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

		// 打开文件不成功，且因为文件不存在，创建文件
		if(!IsOpen() && GetLastError() == 2)
		{
			m_hFile = CreateFileA(m_pszFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		}

		if(IsOpen())
			SetFilePointer(m_hFile, 0, NULL, FILE_END);

		return IsOpen();
	}

	DWORD Write(LPCVOID lpBuffer, DWORD dwLength)
	{
		DWORD dwWriteLength = 0;

		if(IsOpen())
			WriteFile(m_hFile, lpBuffer, dwLength, &dwWriteLength, NULL);

		return dwWriteLength;
	}

	// 写日志，可以扩展修改
	virtual void WriteLog(LPCVOID lpBuffer, DWORD dwLength, bool bRecordTime = false)
	{
		time_t now;
		char szTemp[64] = {0};
		DWORD dwWriteLength = 0;

		if(IsOpen())
		{
			if(bRecordTime)
			{
				time(&now);
				strftime(szTemp, sizeof(szTemp), "%Y-%m-%d %H:%M:%S  ", localtime(&now));
				WriteFile(m_hFile, szTemp, strlen(szTemp), &dwWriteLength, NULL);
			}

			WriteFile(m_hFile, lpBuffer, strlen((char*)lpBuffer), &dwWriteLength, NULL);

			FlushFileBuffers(m_hFile);
		}
	}

	void Lock(void)
	{
		::EnterCriticalSection(&m_csLock);
	}

	void Unlock(void)
	{
		::LeaveCriticalSection(&m_csLock);
	}
};
