////////////////////////////////////////////////////////////////////////////////
//                                                                             /
// 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_PROVIDER_H
#define BK_API_PROVIDER_H

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

#if !defined(NI_MAXHOST)
    #define NI_MAXHOST 1025
#endif

#define STREAM_EX_LOCAL_SETTINGS TM("Use local settings")

namespace Bk
{
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Stream connection state </summary>
    enum eStreamConnection
    {
        /// <summary> State is unknown </summary>
        eStreamConUnknown = -1,
        /// <summary> Connection is on line </summary>
        eStreamConOnline  =  0,
        /// <summary> Connection is off line </summary>
        eStreamConOffline,
        /// <summary> Connection is closed by remote side </summary>
        eStreamConClosed,
        /// <summary> Connection is filtered </summary>
        eStreamConFiltered               
    };


    PRAGMA_PACK_ENTER(8)

    #define MAX_NODE_NAME_LENGTH                             NI_MAXHOST
    #define MAX_PROCESS_NAME_LENGTH                          128

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Stream description structure </summary>
    struct stStreamInfo
    {
        /// <summary> GUID of the stream: BK_GUID_STREAM_TRACE, BK_GUID_STREAM_TELEMETRY, etc. </summary>
        GUID             sType_GUID;
        /// <summary> Protocol version </summary>
        tUINT16          wProtocol_Version;
        /// <summary> network address: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740504%28v=vs.85%29.aspx </summary>
        sockaddr_storage sAddress;
        /// <summary> name of the remote host : http://msdn.microsoft.com/en-us/library/windows/desktop/ms738531(v=vs.85).aspx </summary>
        tXCHAR           pNode[MAX_NODE_NAME_LENGTH];
        /// <summary> remote process ID, system dependent </summary>
        tUINT32          dwProcess_ID;
        /// <summary> remote process creation time </summary>
        FILETIME         sProcess_Time;
        /// <summary> TRUE: data has big-endian format, FALSE - little endian </summary>
        tBOOL            bIs_BigEndian;
        /// <summary> remote process name </summary>
        tXCHAR           pProcess_Name[MAX_PROCESS_NAME_LENGTH];
    }ATTR_PACK(8);


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Stream state description structure </summary>
    struct stStreamStatus
    {
        /// <summary> Stream state </summary>
        eStreamConnection eConnection;
        /// <summary> Off-line period in milliseconds </summary>
        tUINT32           dwDown_Time; 
    }ATTR_PACK(8);

    PRAGMA_PACK_EXIT()

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Extra stream interface, allows to get access to stream parameters and state </summary>
    class IStreamEx
        : public virtual Bk::IUnknown
    {
    public:
        /// <summary> Initialize stream using session key </summary>
        /// <param name="i_pSession"> session key </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Initialize(const tXCHAR *i_pSession) = 0;

        /// <summary> Retrieves stream status </summary>
        /// <param name="o_pActive"> TRUE if stream is alice, False otherwise, output parameter </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Is_Active(tBOOL *o_pActive) = 0;

        /// <summary> Retrieves stream status </summary>
        /// <param name="o_pStatus"> stream status, output parameter </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Get_Status(Bk::stStreamStatus *o_pStatus) = 0;

        /// <summary> Retrieves stream properties </summary>
        /// <param name="o_rRoot"> stream properties, output parameter </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Get_Root(CProperty *&o_rRoot) = 0;

        /// <summary> Close stream and notify client </summary>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Close() = 0;

        /// <summary> Increases object reference counter </summary>
        /// <returns> new value of reference counter </returns>  
        virtual tINT32 __stdcall Add_Ref() = 0;

        /// <summary> Decreases object reference counter. If 0 - object will be self-destroyed </summary>
        /// <returns> new value of reference counter </returns>  
        virtual tINT32 __stdcall Release() = 0;
    };//Bk::IStreamEx
                  

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Extra telemetry stream interface, allows to get access to stream parameters and state </summary>
    class IStreamExTrace
        : public virtual Bk::IStreamEx
    {
    public:
        /// <summary> Update trace module </summary>
        /// <param name="sP7Trace_Module"> module descriptor </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Update(void *i_pModule) = 0;
    };

                  
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Extra telemetry stream interface, allows to get access to stream parameters and state </summary>
    class IStreamExTelemetry
        : public virtual Bk::IStreamEx
    {
    public:
        /// <summary> Update telemetry counter value </summary>
        /// <param name="i_dwID"> counter ID </param>
        /// <param name="i_pName"> counter name </param>
        /// <param name="i_bOn"> On/Off state </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Update_Counter(tUINT32 i_dwID, const tXCHAR *i_pName, tBOOL i_bOn) = 0;
    };
                          

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary> Provider interface, responsible for streams data sending, receiving and forwarding </summary>
    class IProvider
        : public virtual Bk::IUnknown
    {
    public:
        /// <summary> Add source to provider, if source isn't supported function will return eErrorNotSupported </summary>
        /// <param name="i_pSource"> source ID </param>
        /// <param name="o_rToken"> source token, output parameter </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Add_Source(const tXCHAR *i_pSource, void *&o_rToken) = 0;

        /// <summary> Del source using token </summary>
        /// <param name="i_pToken"> source token </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Del_Source(const void *i_pToken) = 0;

        /// <summary> Get progress, for stream providers - always 0 </summary>
        /// <param name="o_rProgress"> progress in range [0..100], output parameter </param>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Get_Progress(tUINT32 &o_rProgress) = 0;

        /// <summary> Exceptional shutdown, to close streams </summary>
        /// <returns>Bk::eResult::eOk in case of success</returns>  
        virtual Bk::eResult __stdcall Exceptional_Shutdown() = 0;
    };//Bk::IProvider
}


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



/// <summary> create provide function prototype </summary>
#define BK_CREATE_PROVIDER "Create_Provider"
typedef Bk::eResult (__cdecl *fnBkCreateProvider)(Bk::IUnknown   *i_pCore,    //[Inp] Core interface
                                                  Bk::IBNode     *i_pNode,    //[Inp] stored configuration node
                                                  CProperty      *i_pProp,    //[Inp] properties
                                                  Bk::IProvider **o_pProvider //[Out] result provider interface
                                                 );

#endif //BK_API_PROVIDER_H