////////////////////////////////////////////////////////////////////////////////
//                                                                             /
// 2012-2019 (c) Baical                                                        /
//                                                                             /
// This library is free software; you can redistribute it and/or               /
// modify it under the terms of the GNU Lesser General Public                  /
// License as published by the Free Software Foundation; either                /
// version 3.0 of the License, or (at your option) any later version.          /
//                                                                             /
// This library is distributed in the hope that it will be useful,             /
// but WITHOUT ANY WARRANTY; without even the implied warranty of              /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU           /
// Lesser General Public License for more details.                             /
//                                                                             /
// You should have received a copy of the GNU Lesser General Public            /
// License along with this library.                                            /
//                                                                             /
////////////////////////////////////////////////////////////////////////////////
#ifndef BK_VTRACE_H
#define BK_VTRACE_H

#define TRACE_MESSAGE_LENGTH                                      (0x2000)//8912


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CViewTrace
    : public CConsoleWnd
    , public Bk::IViewer 
{
    struct stColor
    {
        IConsole::eColor eFg;
        IConsole::eColor eBg;
    };

    struct stTime
    {
        tUINT32  dwYear;          //year
        tUINT32  dwMonth;         //month
        tUINT32  dwDay;           //day
        tUINT32  dwHour;          //hour
        tUINT32  dwMinutes;       //minute
        tUINT32  dwSeconds;       //seconds
        tUINT32  dwMilliseconds;  //milliseconds
        tUINT32  dwMicroseconds;  //microseconds
        tUINT32  dwNanoseconds;   //nanoseconds
        tUINT64  qwRawTime;       //number of 100-nanosecond intervals since 01.01.1601 (UTC)
        tUINT64  qwRawTimeOffset; //offset of 100-nanosecond intervals since prev. item
        tXCHAR  *pBuffer;         //output buffer
        size_t   szBuffer;        //max buffer size
        size_t   szLengh;         //expected length
    };

    typedef size_t (*fnPrintTime)(const stTime &i_rTime);

    enum eColumn
    {
        eIndex = 0,
        eId,
        eLevel,
        eModule,
        eProcessor,
        eThread,
        eFile,
        eLine,
        eFunction,
        eTime,
        eText,

        eColumnMax
    };

    enum eTimeFormat
    {
        eTimeFull = 0,
        eTimeMedium,  
        eTimeShort,   
        eTimeOffset,  
        eTimeDiff, 
        eTimeFormatMax
    };

    //put volatile variables at the top, to obtain 32 bit alignment. 
    //Project has 8 bytes alignment by default
    tINT32 volatile         m_lReference;

    CConsole               *m_pConsole;
    Bk::IStorageReader     *m_iReader;
    Bk::ITraceReader       *m_iTrace;

    Bk::IBNode             *m_pNode;
    Bk::IStreamEx          *m_iExtra; 
    CProperty              *m_pProp;
    Bk::IViewersEnumerator *m_pEnum;           

    const tXCHAR           *m_pLevel[EP7TRACE_LEVEL_COUNT];
    const tXCHAR           *m_pTimeFormat[eTimeFormatMax];
    stColor                 m_pColors[EP7TRACE_LEVEL_COUNT];
    tXCHAR                 *m_pText;
    size_t                  m_szText;

    tXCHAR                 *m_pMessage;
    size_t                  m_szMessage;

    eTimeFormat             m_eTimeFormat; 
    tUINT64                 m_qwStreamTime;
    fnPrintTime             m_pTimeFormatters[eTimeFormatMax];
    tBOOL                   m_bFollowLast;

public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CViewTrace(CConsole               *i_pConsole,
               Bk::IBNode             *i_pNode,
               Bk::IStorageReader     *i_iReader,
               Bk::IStreamEx          *i_iExtra, 
               CProperty              *i_pProp,
               Bk::IViewersEnumerator *i_pEnum            
              );
    virtual ~CViewTrace();
    tBOOL          Is_Failed() { return m_bError; }
    virtual size_t Print();
    virtual tBOOL  ProcessKey(tUINT16 i_xChar, tBOOL &o_rExit);

public: //IViewer
    virtual Bk::eResult __stdcall Show();
    virtual Bk::eResult __stdcall Close() { return Bk::eOk; };
    virtual Bk::eResult __stdcall Set_Position(Bk::IViewer *i_pSrc,
                                               tUINT32      i_uiYear,
                                               tUINT32      i_uiMonth,
                                               tUINT32      i_uiDay,
                                               tUINT32      i_uiHour,
                                               tUINT32      i_uiMin,
                                               tUINT32      i_uiSec,
                                               tUINT32      i_uiMilsec,
                                               tUINT32      i_uiMicsec,
                                               tUINT32      i_uiNansec
                                               ) 
    {
        UNUSED_ARG(i_pSrc);
        UNUSED_ARG(i_uiYear);
        UNUSED_ARG(i_uiMonth);
        UNUSED_ARG(i_uiDay);
        UNUSED_ARG(i_uiHour);
        UNUSED_ARG(i_uiMin);
        UNUSED_ARG(i_uiSec);
        UNUSED_ARG(i_uiMilsec);
        UNUSED_ARG(i_uiMicsec);
        UNUSED_ARG(i_uiNansec);
        return Bk::eOk;    
    }

    Bk::eResult __stdcall Set_Visible(tBOOL i_bVisible)
    {
        UNUSED_ARG(i_bVisible);
        return Bk::eOk;    
    }

    virtual tBOOL __stdcall Closed() 
    {
        return FALSE;
    }

    virtual tINT32 __stdcall Add_Ref()
    {
        return ATOMIC_INC(&m_lReference);
    }

    virtual tINT32 __stdcall Release()
    {
        tINT32 l_lResult = ATOMIC_DEC(&m_lReference);
        if ( 0 >= l_lResult )
        {
            delete this;
        }

        return l_lResult;
    }

protected:
    static size_t WriteField(size_t i_szLength, tXCHAR *o_pBuffer, size_t  i_szBuffer, const tXCHAR *i_pFormat, ...);
    static size_t FormatTimeFull(const stTime &i_rTime);
    static size_t FormatTimeMedium(const stTime &i_rTime);
    static size_t FormatTimeShort(const stTime &i_rTime);
    static size_t FormatTimeDiff(const stTime &i_rTime);
};

#endif //BK_VTRACE_H
