/**************************************************************************
*   Copyright (c) 2011, 2023 Cisco Systems, Inc.
*   All Rights Reserved. Cisco Highly Confidential.
***************************************************************************
*
*   File:   PrivateApi.h
*   Date:   01/2011
*
***************************************************************************
*   VPN C API Internal C++ class
***************************************************************************/
#ifndef _MYAPI_
#define _MYAPI_

#include "ClientIfc.h"
#include "vpncapi.h"
#include <string>
#include <sstream>

#if defined(_WIN32)
    #include <process.h>
    #include <windows.h>
#else
    #include <pthread.h>
    #include <string.h>
#endif

#if defined(_WIN32)
    #define strdup_f _strdup //silence compiler warnings
    #define snprintf_f _snprintf_s

    #define VPNCAPI_MANUAL_LOCK                 CRITICAL_SECTION
    #define VPNCAPI_INIT_LOCK(_lock_ref_)       InitializeCriticalSection(_lock_ref_)
    #define VPNCAPI_ACQUIRE_LOCK(_lock_ref_)    EnterCriticalSection(_lock_ref_)
    #define VPNCAPI_RELEASE_LOCK(_lock_ref_)    LeaveCriticalSection(_lock_ref_)
#else
    #define strdup_f strdup
    #define snprintf_f snprintf

    #define VPNCAPI_MANUAL_LOCK                 pthread_mutex_t
    #define VPNCAPI_INIT_LOCK(_lock_ref_)       pthread_mutex_init(_lock_ref_, NULL)
    #define VPNCAPI_ACQUIRE_LOCK(_lock_ref_)    pthread_mutex_lock(_lock_ref_)
    #define VPNCAPI_RELEASE_LOCK(_lock_ref_)    pthread_mutex_unlock(_lock_ref_)

    #define A2T
    #define A2CT
    #define W2T
    #define W2CT
    #define T2A
    #define T2CA
    #define T2W
    #define USES_CONVERSION
#endif

enum vpncapi_log_sev
{
    LOGERR,
    LOGWARN,
    LOGINFO
};

void vpncapi_log2(vpncapi_log_sev sev, std::string pszMessage);

#define vpncapi_log(sev, ...) \
    std::stringstream ss;                                         \
    char buff[128];                                               \
    snprintf_f(buff, 128, __VA_ARGS__);                                 \
    ss << __FILE__ << ":" << __LINE__ <<" in " << __FUNCTION__ <<"(): " << buff; \
    vpncapi_log2(sev, ss.str())


class PrivateApi : public ClientIfc
{
    protected:

        virtual void StatsCB(VPNStats &stats);

        virtual void StateCB(const VPNState state,
                             const VPNSubState subState,
                             const tstring stateString);

        virtual void BannerCB(const tstring &banner);

        virtual void PreConnectReminderCB(IN const tstring &rtstrPreConnectReminder);

        virtual void NoticeCB(const tstring &notice,
                              const MessageType type,
                              const bool bSensitive);

        virtual void ExitNoticeCB(const tstring &tstrNotice,
                                  const int returnCode);

        virtual void ServiceReadyCB();

        virtual void UserPromptCB(ConnectPromptInfo &ConnectPrompt);

        virtual void EventAvailable();

        virtual void WMHintCB(const WMHint hint, const WMHintReason reason);

        virtual void deliverWebLaunchHostCB(const tstring &activeHost);

        virtual void CertBlockedCB(const tstring &rtstrUntrustedServer);

        virtual void CertWarningCB(const tstring &rtstrUntrustedServer,
                                   const std::list<tstring> &rltstrCertErrors,
                                   bool bAllowImport);

    public:
        PrivateApi(VPNAPI_CALLBACKS* pCallbacks);
        virtual ~PrivateApi();

        bool CSetPromptEntryValue(const char *pszEntryName, const char *pszEntryValue);
        void setEnrollmentCA(bool bEnroll);

        PREFERENCE_INFO* CGetPreferences();

        bool CSavePreferences();

        bool CPreferenceSetValue(const char *pszPreferenceName, const char *pszValue);

        PREFERENCE* CGetPreferenceByName(const char* pszPreferenceName);

        const char* CGetDefaultHostname();
        STRING_LIST CGetHostnames();

        STRING_LIST CGetPromptEntryNames();

        bool CIsEventAvailable();

        void setCanceled(bool bIsCanceled);

        void UserSubmit();

#if defined(PLATFORM_ANDROID)
        void ClientCertificateCB(std::vector< std::pair<uint32_t, uint8_t*> > certList);
#endif

    private:

        //
        // PRIVATE DATA
        //

        VPNAPI_CALLBACKS* m_pCallbacks;
        ConnectPromptInfo* m_pConnectPrompt;
        std::shared_ptr<PreferenceInfo> m_spPreferenceInfo;

        /*
         * All data structures prefixed by "m_C" are temporary data buffers intended to
         * facilitate retrieval by vpncapi user. PrivateApi owns pointers to these buffers
         * and provide shallow references to C client. A soft reference is valid until next
         * function call to retrieve that reference, unless noted otherwise
         */

        // prompts
        CONNECT_PROMPT_INFO *m_pCPromptInfo;
        std::vector<PROMPT_ENTRY*> m_CPromptEntries;
        std::map<std::string, PROMPT_ENTRY*> m_PromptEntryMap;
        std::vector<const char*> m_CPromptEntryNames;

        // stats
        VPN_STATS* m_pCVpnStats;
        std::vector<ROUTE_INFO*> m_CStatsSecureRoutes;
        std::vector<ROUTE_INFO*> m_CStatsNonSecureRoutes;
        std::vector<PROTOCOL_INFO*> m_CStatsProtocolInfo;
        std::vector<FIREWALL_INFO*> m_CStatsFirewallInfo;

        // preferences
        const unsigned int m_uiPreferenceCount;
        PREFERENCE_INFO m_CPreferenceInfo;
        PREFERENCE** m_CAllControllablePrefs;
        std::vector<PREFERENCE*> *m_CPrefChildren;
        std::vector<PREFERENCE*> m_CSortedPrefs;

        // hostnames
        std::string m_strDefaultHostname;
        std::vector<const char*> m_Hostnames;
        // callback data
        std::string m_strState;
        std::string m_strBanner;
        std::string m_strPreConnectReminder;
        std::string m_strNotice;
        std::string m_strExitNotice;
        std::string m_strWebLaunchHost;
        // indicates to polling vpncapi user that an event is available - BUGBUG -- remove when
        // cdriver is converted to the event model
        bool m_bEventAvailable;
        VPNCAPI_MANUAL_LOCK m_EventLock;

        //
        // PRIVATE METHODS
        //

        // cleanup/clear data buffers
        void resetCPreferences();
        void resetCUserPrompt();
        void resetCVpnStats();

        // helpers for mapping C++ objects to C structs defned in vpncapi.h
        PREFERENCE* createCPreference(Preference *pPref);
        void deleteCPreference(PREFERENCE *&pCPreference);

        PROMPT_ENTRY* createCPromptEntry(const PromptEntry *pPromptEntry);
        void deleteCPromptEntry(PROMPT_ENTRY *&pCPromptEntry);

        CONNECT_PROMPT_INFO* createCPromptInfo(const ConnectPromptInfo &ConnectPrompt);
        void deleteCPromptInfo(CONNECT_PROMPT_INFO *&pPromptInfo);

        VPN_STATS* createCVpnStats(VPNStats &stats);
        void deleteCVpnStats(VPN_STATS *&pCStats);

        ROUTE_INFO* createCRouteInfo (RouteInfo* pRouteInfo);
        void deleteCRouteInfo(ROUTE_INFO *&pRouteInfo);

        PROTOCOL_INFO* createCProtocolInfo(ProtocolInfo* pProtocolInfo);
        void deleteCProtocolInfo(PROTOCOL_INFO *&pCProtocolInfo);

        FIREWALL_INFO* createCFirewallInfo(FirewallInfo* pFirewallInfo);
        void deleteCFirewallInfo(FIREWALL_INFO *&pCFirewall);
};

#endif //_MYAPI_
