////////////////////////////////////////////////////////////////////////////////
//                                                                             /
// 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_API_STORAGE_H
#define BK_API_STORAGE_H

/// <summary> Extension of trace storage </summary>
#define BK_STORAGE_TRACE_FILE_EXT        TM(".p7t")
/// <summary> Extension of telemetry storage </summary>
#define BK_STORAGE_TELEMETRY_FILE_EXT_V1 TM(".p7m")
#define BK_STORAGE_TELEMETRY_FILE_EXT_V2 TM(".p7tm2")
/// <summary> Extension of dump storage </summary>
#define BK_STORAGE_DUMP_FILE_EXT         TM(".p7d")

#include "PAPI.h"
#include "PAPI_Node.h"
#include "PAPI_Provider.h"
#include "Prop.h"

namespace Bk
{
    PRAGMA_PACK_ENTER(8)
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Storage information </summary>
    struct stStorageInfo
    {
        /// <summary> Storage type GUID: file, database, etc. </summary>
        GUID sType;
        /// <summary> Network address </summary>
        sockaddr_storage sAddress;
        /// <summary> Host name: http://msdn.microsoft.com/en-us/library/windows/desktop/ms738531(v=vs.85).aspx </summary>
        tXCHAR pNode[NI_MAXHOST];
        /// <summary> Process ID </summary>
        tUINT32 dwProcess_ID;
        /// <summary> Process creation time </summary>
        FILETIME sProcess_Time; //time of process creation
        /// <summary> Process name </summary>
        tXCHAR pProcess_Name[128];
        /// <summary> Stream creation time </summary>
        FILETIME sStream_Time;
        /// <summary> Stream name </summary>
        tXCHAR pStream_Name[64];
    }ATTR_PACK(8);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Data chunks list </summary>
    struct stDataChunk
    {
        /// <summary> Data pointer </summary>
        const tUINT8 *pBuffer;
        /// <summary> Data size </summary>
        size_t        szBuffer;    
        /// <summary> Pointer to next element, if NULL => end of the list </summary>
        stDataChunk  *pNext;
    }ATTR_PACK(8);
    PRAGMA_PACK_EXIT()


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Storage description level </summary>
    enum eStorageDescLevel
    {
        eStorageDescLevelNormal,
        eStorageDescLevelWarning,
        eStorageDescLevelError,
        eStorageDescLevelCritical,
        eStorageDescLevelMax
    };

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Storage description </summary>
    struct stStorageDesc
    {
        /// <summary> description level, provided by storage </summary>
        Bk::eStorageDescLevel eLevel;
        /// <summary> preallocated text buffer </summary>
        tXCHAR               *pText;
        /// <summary> preallocated text buffer size in chars </summary>
        size_t                szTextMax;
    };

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Storage reader interface </summary>
    class IStorageReader
        : public virtual Bk::IUnknown
    {
    public:
        /// <summary>Retrieve sotrage information</summary>
        /// <param name="o_pInfo">Storage info structure, output parameter</param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Get_Info(Bk::stStorageInfo *o_pInfo) = 0;

        /// <summary>
        /// Get path of the current reader.
        /// N.B.: o_pPath pointer has to be released by calling free(*o_pPath);
        /// </summary>
        /// <param name="o_pPath">path to storage, output parameter</param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Get_Path(tXCHAR **o_pPath) = 0;
                                                                           
        /// <summary> Get size of the storage in bytes </summary>
        /// <param name="o_pSize"> size in bytes, output parameter</param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Get_Size(tUINT64 *o_pSize) = 0;

        /// <summary> Get text description of the storage & stream </summary>
        /// <param name="io_rDesc"> description </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Get_Description(Bk::stStorageDesc &io_rDesc) = 0;

        /// <summary> Delete current storage, if storage is blocked by other readers it will be deleted later </summary>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Delete() = 0;
    };


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Base storage interface </summary>
    class IStorage
        : public virtual Bk::IUnknown
    {
    public:
        /// <summary>Retrieve sotrage information</summary>
        /// <param name="o_pInfo">Storage info structure, output parameter</param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Get_Info(Bk::stStorageInfo *o_pInfo) = 0;

        /// <summary> 
        /// Releases all internal resources for writing, it allow to save, memory for buffers and internal resources on closed streams
        /// </summary>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult   __stdcall Uninit_Writer() = 0;

        /// <summary> Deliver packet to storage </summary>
        /// <param name="i_pBuffer"> packet data </param>
        /// <param name="i_dwSize"> packet size in bytes </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult   __stdcall Put_Packet(Bk::stDataChunk *i_pChunk) = 0;

        /// <summary> 
        /// function will put stream Extra interface, this interface provides some extra functionality for stream management - check is 
        /// stream alive and other options
        /// </summary>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult   __stdcall Put_Stream_Ex(Bk::IStreamEx *i_pEx) = 0;
    };
}




////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////// Plugins function prototypes ////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/// <summary> create storage function prototype </summary>
#define BK_CREATE_STORAGE "Create_Storage"
typedef Bk::eResult (__cdecl *fnBkCreateStorage)(Bk::IStorage    **o_pStorage,  //[Out] result storage interface
                                                 Bk::stStreamInfo *i_pInfo,     //[Inp] stream info
                                                 Bk::IBNode       *i_pNode,     //[Inp] stored configuration node
                                                 CProperty        *i_pProp      //[Inp] properties
                                                );

/// <summary> open storage function prototype </summary>
#define BK_OPEN_STORAGE "Open_Storage"
typedef Bk::eResult (__cdecl *fnBkOpenStorage)(Bk::IStorageReader **o_pReader,  //[Out] result reader interface
                                               Bk::IBNode          *i_pNode,    //[Inp] stored configuration node
                                               CProperty           *i_pProp,    //[Inp] properties
                                               const tXCHAR        *i_pPath     //[Inp] File/database/network addr path
                                              );
#endif //BK_API_STORAGE_H