//////////////////////////////////////////////////////////////////////
// V7LogProvider.h: interface for Log data provider for CursorGrid
// control for V7.
// Written by Vasiliy Trapeznikov aka trav, mailto: trav78@yandex.ru
// Version: n/a
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_V7LOGPROVIDER_H__0C55D3E5_FC82_459F_B02F_C771793674E7__INCLUDED_)
#define AFX_V7LOGPROVIDER_H__0C55D3E5_FC82_459F_B02F_C771793674E7__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "DataProvider.h"
#include "V7DataProvider.h"
#include "../mycontextbase.h"

#define LOG_DP_FIELD_COUNT             10
#define LOG_DP_MIN_READ_BLOCK_SIZE     1024
#define LOG_DP_MAX_READ_BLOCK_SIZE     65536
#define LOG_DP_NEW_ROW_10              0x0A
#define LOG_DP_NEW_ROW_13              0x0D
#define LOG_DP_NEW_LINE_LENGTH         2
#define LOG_DP_DATE_TIME_LENGTH        18
#define LOG_DP_MIN_ROW_LENGTH          27
#define LOG_DP_TRIM_10_13_NO           0
#define LOG_DP_TRIM_10_13_LEFT         1
#define LOG_DP_TRIM_10_13_RIGHT        2
// для фильта
#define LOG_DP_FILTER_CLEAR            0
#define LOG_DP_FILTER_DATE             1
#define LOG_DP_FILTER_TIME             2
#define LOG_DP_FILTER_USER             3
#define LOG_DP_FILTER_MODE             4
#define LOG_DP_FILTER_EVENTTYPE        5
#define LOG_DP_FILTER_EVENT            6
#define LOG_DP_FILTER_CATEGORY         7
#define LOG_DP_FILTER_COMMENT          8
#define LOG_DP_FILTER_OBJECT           9
#define LOG_DP_FILTER_PRESENT          10
#define LOG_DP_FILTER_OBJECTKIND       11
#define LOG_DP_FIELD_POSITION          12
#define LOG_DP_FILTER_USING_BUFFER     13
// второй параметр в SetFilter
#define LOG_DP_FILTER_PARAM_NO         0
#define LOG_DP_FILTER_PARAM_STR        1
#define LOG_DP_FILTER_PARAM_OBJ        2
#define LOG_DP_FILTER_PARAM_VL         4
#define LOG_DP_FILTER_PARAM_STR_VL     LOG_DP_FILTER_PARAM_STR|LOG_DP_FILTER_PARAM_VL
#define LOG_DP_FILTER_PARAM_OBJ_VL     LOG_DP_FILTER_PARAM_OBJ|LOG_DP_FILTER_PARAM_VL



class CV7LogProvider;

class CLogRow : public CDataRow, public CV7DataRow
{
    friend class CV7LogProvider;
public:
    CLogRow(LARGE_INTEGER liPosition, CString* pRow);
    virtual ~CLogRow();

    //CDataRow
    virtual int GetFieldCount() { return LOG_DP_FIELD_COUNT; };
    virtual int GetFieldIndexOf(LPCSTR szFieldName);
    virtual LPCSTR GetFieldName(int nIndex);
    virtual DataType GetFieldType(int nIndex) {return dtText;};
    virtual void FormatField(int nIndex, CString& strValue);

    //CV7DataRow
    virtual const CValue& GetValue(int nIndex) const;

private:
	LARGE_INTEGER m_liPosition;

	CValue* m_ppValues[LOG_DP_FIELD_COUNT];

	const static CValue m_vEmpty;

	const static struct FieldsNames
	{
		LPCSTR strRus;
		LPCSTR strEng;
	} m_sFields[];

};



class CV7LogProvider : 
	public CMyContextBase,
	public CDataProvider, 
	public CV7DataProvider  
{
    DECLARE_DYNCREATE(CV7LogProvider);
public:
	
	CV7LogProvider();
	virtual ~CV7LogProvider();

	BOOL SetPeriod(CValue& Result, CValue** ppValue);
	BOOL DefaultPeriod(int nParam, CValue* param) const;
	BOOL GetBegOfPeriodDate(CValue& Value) const;
	BOOL GetEndOfPeriodDate(CValue& Value) const;
	BOOL GetBegOfPeriodTime(CValue& Value) const;
	BOOL GetEndOfPeriodTime(CValue& Value) const;

	BOOL ChangeFilter(CValue& Result, CValue** ppValue);
	BOOL SetFilter(CValue& Result, CValue** ppValue);
	BOOL DefaultFilter(int nParam, CValue* param) const;

	BOOL SetScanDeep(CValue& Result, CValue** ppValue);
	BOOL GetScanDeep(CValue& Value) const;
	BOOL GetLastScanDate(CValue& Value) const;
	BOOL DefaultScanDeep(int nParam, CValue* param) const;


	BOOL OpenFile(CValue& Result, CValue** ppValue);
	BOOL CloseFile(CValue** ppValue);


	BOOL SelectLines(CValue& Result, CValue** ppValue);
	BOOL DefaultSelectLines(int nParam, CValue* param) const;
	BOOL GetLine(CValue& Result, CValue** ppValue);

	BOOL GetUsingBuffer(CValue& Value) const;

	BOOL RowGetPosition(CValue& Value) const;
	BOOL RowGetDate(CValue& Value) const;
	BOOL RowGetTime(CValue& Value) const;
	BOOL RowGetUser(CValue& Value) const;
	BOOL RowGetMode(CValue& Value) const;
	BOOL RowGetEventType(CValue& Value) const;
	BOOL RowGetEvent(CValue& Value) const;
	BOOL RowCategory(CValue& Value) const;
	BOOL RowGetComment(CValue& Value) const;
	BOOL RowGetObject(CValue& Value) const;
	BOOL RowGetObjectPresent(CValue& Value) const;

	BOOL SetPeriodEx(CValue& Result, CValue** ppValue);
	BOOL DefaultPeriodEx(int nParam, CValue* param) const;

	BOOL GetLogFileName(CValue& Value) const;
	BOOL SetLogFileName(CValue const& Value);

    DECLARE_MY_CONTEXT()

    //CDataProvider
public:
    virtual void QueryRows(CDataRow* pRowFrom, int nRowsCount, int nPageSizeHint);
    virtual CDataRow* Fetch();
    virtual BOOL RefreshRow(CDataRow* pRowFrom);
    virtual BOOL CompareRows(CDataRow* pRow1, CDataRow* pRow2) const;
protected:
    virtual void OnAttach();
    virtual void OnDetach() { CloseLog(); };

    //CV7DataProvider
public:
    virtual CV7DataRow* GetV7DataRow(CDataRow* pDataRow) const;
    virtual void GetRowValue(CDataRow* pDataRow, CValue& value) const;
    virtual CDataRow* BuildRowByValue(const CValue& value);

private:

	enum ProviderMode
	{
		pmNormalBrowse=0,
		pmBoundsSearch,
		pmPeriodBrowse,
		pmInvalidPeriod
	} m_eProviderMode;

	enum GetRowResult
	{
		grrMismatch=0,
		grrMatch,
		grrNoMoreRows,
		grrEscPressed
	};

	enum AddingMode
	{
		amNormal=0,
		amToHead,
		amToTail
	};

	void Init();

	BOOL OpenLog();
	void CloseLog();
	BOOL ReadLog(const DWORD dwBytesToRead, DWORD& dwBytesRead, const DWORD dwHowToTrim=LOG_DP_TRIM_10_13_NO);
	BOOL SetPosition(LARGE_INTEGER &liPosition, const DWORD dwMoveMethod);

	BOOL GetRowByPosition(const BOOL bCheckEnd, LARGE_INTEGER &liPosition);

	BOOL GetRow(const BOOL bFetch, BOOL bBackward, LARGE_INTEGER &liRowPosition, CString &strRow, ULONGLONG* pqwDate = NULL);
	BOOL SearchBound(const BOOL bLowerBound, const ULONGLONG& qwSearchDate);
	BOOL IsDateTimeValid(const BOOL bCheckDateTime, CString& strDateTime, ULONGLONG* pqwDateTime = NULL) const;
	BOOL SetPeriodInternal(ULONGLONG& qwBegDate, ULONGLONG& qwEndDate);

	void GetModeAndCategory(const CIStringMapToIndex* const pMap, const BOOL bMode, CString& strCheck) const;

	GetRowResult GetFilteredRow(const BOOL bSeeESC, const BOOL bCheckFilter, BOOL bBackward, LARGE_INTEGER &liRowPosition, CString* pRow, LPDWORD pdwRowLength = NULL, ULONGLONG* pqwDate = NULL);

	inline BOOL BufferMode() const;

	GetRowResult AddRowsToList(const AddingMode HowToAdd, LARGE_INTEGER liFromPosition, LONGLONG &llBytesToRead, LONGLONG &llBytesRead);
	LONGLONG GetBytesToRead(LONGLONG llEndPos = 0) const;

	void GetRowFieldValue(const int nFieldIndex, CValue& Value) const;


	HANDLE m_hLogFile;
	CString m_strBuffer;

	CString m_strLogFileName;


	LARGE_INTEGER m_liCurrentPosition;

	int m_nBufferGrowCount;
	
	
	BOOL m_bSkipRow;
	BOOL m_bStandardBuffer;
	int m_nQueryRowsCount;

	// для выборки строк
	BOOL m_bLinesSelectionEnabled;
	struct CurrentRow
	{
		LONGLONG pos;
		CString fields[LOG_DP_FIELD_COUNT];
	} m_sCurrentRow;

	// для периода
	ULONGLONG m_qwStartLogDate;
	ULONGLONG m_qwBegDate;
	ULONGLONG m_qwEndDate;
	LARGE_INTEGER m_liBegPosition;
	LARGE_INTEGER m_liEndPosition;


	// для фильта
	DWORD m_dwFilter;
	int m_nScanDeep;
	DWORD m_dwLastScanDate;
	BOOL m_bInvalidFilter;

	CString m_strMode;
	CString m_strCategory;
	CString m_strComment;
	CString m_strPresent;

	const static struct FilterInfo
	{
		LPCSTR strEventOrType;
		LPCSTR strMode;
		LPCSTR strCategory;
		UCHAR chSecondParam;
		UCHAR chFilterType;
		UCHAR chParent;
	} m_stFiltersInfo[];

	CIStringMapToIndex m_mapEventType;
	CIStringMapToIndex m_mapEvent;
	CIStringMapToIndex m_mapObject;
	CIStringMapToIndex m_mapObjectKind;
	CMapStringToOb m_mapUser;

	CList<LONGLONG,LONGLONG&> m_RowsList;
	POSITION m_RowPosition;

};


CString GetStringFromTmpl(CString strFindIn, CString& strTmp, const CString& strTmpl, const BOOL& bAddParam);
BOOL GetStringPresent(const CValue* const val, const BOOL bFull, CString& csResult);

#endif // !defined(AFX_V7LOGPROVIDER_H__0C55D3E5_FC82_459F_B02F_C771793674E7__INCLUDED_)
