////////////////////////////////////////////////////////////////////////////////
//                                                                             /
// 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_P7_PROVIDER_H
#define BK_P7_PROVIDER_H



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CProviderP7: 
    public Bk::IProvider
{
public:
    enum eThreadMain
    {
        eThreadMainExit = MEVENT_SIGNAL_0,
        eThreadMainCountSignal
    };

protected:
    struct stStat
    {
        IP7S_Address *pAddress;
        tUINT16       bTidNetIn;
        tUINT16       bTidNetOut;

        stStat(IP7S_Address *i_pAddress)
          : pAddress(i_pAddress)
          , bTidNetIn(P7TELEMETRY_INVALID_ID_V2)
          , bTidNetOut(P7TELEMETRY_INVALID_ID_V2)
        {}
    };


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

    IP7_Server            *m_pServer;
    CDNS_Resolver         *m_pDns_Resolver;
                          
    IP7_Trace             *m_iP7_Trace;
    IP7_Trace::hModule     m_hP7_TraceModule;
    IP7_Telemetry         *m_iP7_Tel;
    CJrTrProxy            *m_pJlTrProxy;
                          
    CMEvent                m_cExit_Event; 
    CThShell::tTHREAD      m_hThread;
    tBOOL                  m_bIsThread;
                          
    CProperty             *m_pPropRoot;

    CBList<CConnectionP7*> m_cConnections; 
    tBOOL                  m_bInitialized;

    Bk::ICore             *m_pCore;


public:
    CProviderP7(Bk::IUnknown *i_pCore, Bk::IBNode *i_pNode, CProperty *i_pProp);

    virtual ~CProviderP7();

    tBOOL Get_Initialized() { return m_bInitialized; }

    tINT32      __stdcall Add_Ref();
    tINT32      __stdcall Release();
    Bk::eResult __stdcall Query_Interface(Bk::eInterface i_eId, void *&o_rUnknown);

    Bk::eResult __stdcall Add_Source(const tXCHAR *i_pSource, void *&o_rToken);
    Bk::eResult __stdcall Del_Source(const void *i_pToken);
    Bk::eResult __stdcall Get_Progress(tUINT32 &o_rProgress);
    Bk::eResult __stdcall Exceptional_Shutdown();

private:

    void  RoutineMain();

    static THSHELL_RET_TYPE THSHELL_CALL_TYPE Static_Routine(void *i_pContext)
    {
        CProviderP7 * l_pRoutine = (CProviderP7 *)i_pContext;
        if (l_pRoutine)
        {
            l_pRoutine->RoutineMain();
        }

        CThShell::Cleanup();
        return THSHELL_RET_OK;
    } 
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
extern "C" P7_EXPORT Bk::eResult __cdecl Get_Plugin_Info(Bk::stPluginInfo *o_pInfo);
extern "C" P7_EXPORT Bk::eResult __cdecl Create_Provider(Bk::IUnknown   *i_pCore,
                                                         Bk::IBNode     *i_pNode,
                                                         CProperty      *i_pProp,
                                                         Bk::IProvider **o_pProvider);

#endif //BK_P7_PROVIDER_H