/**************************************************************************
*   Copyright (c) 2006, 2022-2023 Cisco Systems, Inc.
*   All Rights Reserved. Cisco Highly Confidential.
***************************************************************************
*
*   File: ClientIfc.h
*   Date: 11/2006
*
***************************************************************************
*   Client Interface class implementation for the Client API.
***************************************************************************/

#ifndef _CLIENTIFC_
#define _CLIENTIFC_


/**
* This is the main interface class for applications that implement the
* Cisco AnyConnect Secure Mobility VPN API.  A program wishing to use the API must create a
* class that extends the ClientIfc class.  This new class is required to
* provide implementations for the pure virtual methods found in the protected
* section (for example, StatsCB).
*
* Finally, the public section contains methods that are available for
* managing the API.  These include methods like attach and connect.
*
* A client must implement the CB (abstract) methods found in the protected
* section of this interface.
*
*/

#include "ClientIfcCommon.h"
#include "api.h"
#include "ClientIfcBase.h"
#include "VPNStats.h"
#include "ConnectPromptInfo.h"
#include "Preference.h"
#include "PreferenceInfo.h"

class ClientIfcData;

class VPN_VPNAPI ClientIfc :
    protected ClientIfcBase
{
    friend class ClientIfcData;

    protected:

        ClientIfc();

        virtual ~ClientIfc();

        /**
        * Callback Declarations inherited from ClientIfcBase.
        * 
        * Virtual Abstract Callback Method Declarations:
        *   StatsCB
        *   StateCB
        *   BannerCB
        *   NoticeCB
        *   CertBannerCB
        *   ServiceReadyCB
        *   UserPromptCB
        *   CertBlockedCB
        *   CertWarningCB (2 signatures)
        *   ClientCertificateCB
        * 
        * Virtual Callback Method Declarations:
        *   PreConnectReminderCB
        *   ExitNoticeCB
        *   WMHintCB
        *   deliverWebLaunchHostCB
        *   EventAvailable
        *   ImportPKCS12ResultCB
        *   AgentDetachedCB
        */

    public:

        /**
         * After the ClientIfc class has been created, the client implementation
         * must invoke this method prior to attempting connections,
         * retrieving statistics, etc.  If successful, this method returns
         * true.  If not successful, it returns false and returns a notice error
         * message to the user.
         *
         * A single call to this method is all that is necessary.  If the
         * attach fails, a message indicating the VPN service is not available
         * is returned.  If the call succeeds, the ServiceReadyCB is
         * called and true is returned.
         *
         * \param ClientType clientType (default ClientType_GUI)
         * Other options: ClientType_GUI_SBL, ClientType_CLI, ClientType_MGMT.
         * ClientType_GUI: indicates that the started program is a GUI
         * application.  With this attribute set to true, the application will
         * now receive WMHints.
         * ClientType_GUI_SBL: SBL (Start Before Logon) is a mode of operation 
         * where a GUI can be launched prior to the normal windows logon sequence.  
         * This allows a VPN tunnel to be activated and used as part of the windows
         * logon sequence. This value is applicable only when a corresponding 
         * argument has been passed to the program by the VPN agent.
         * ClientType_CLI: indicates that the started program is a CLI application.
         * ClientType_MGMT: indicates that the started program is used to initiate
         *                  an AnyConnect management VPN tunnel. This value is
         *                  applicable only to a client launched by AnyConnect VPN agent.
         *
         * \param requestFullCapabilities indicates that the client program is
         * requesting full API capabilities.  Full capabilities allows the
         * client program to connect, disconnect, receive statistics, etc.
         * When full capabilities are not requested or not available, the
         * client program will not be able to establish new VPN connections.
         * Only a client program with full capabilites can do this.  In
         * addition, only the first program requesting full capabilities will
         * be granted this level of access.  The attach method can succeed
         * even if full capabilities is requested but not granted.  To test
         * for this state, use the method ::hasFullCapabilities.
         *
         * \param suppressAutoConnect indicates that the client wishes to
         * override automatically initiating a connection to the last connected
         * secure gateway at startup.  Normally, this is determined by the 
         * value of the AutoConnectOnStart preference.  If this flag is true
         * then an automatic connection will never be initiated, even if 
         * AutoConnectOnStart is enabled.
         */
        bool attach(ClientType clientType = ClientType_GUI,
                    bool requestFullCapabilities = true,
                    bool suppressAutoConnect = true);


        /**
         * After the client program is done, call the detach method to do a
         * graceful cleanup.  This method stops the flow
         * of events and does general cleanup.
         */
        void detach();


        /**
         * When the method ClientIfc::EventAvailable has been overridden in the
         * client application, this method must be called to receive events.
         *
         * It is expected that GUI programs will use EventAvailable as a
         * signal, allowing them to set an event using their native event
         * handler.  When that event fires, the application can call
         * ProcessEvents, which causes the API to deliver events in the
         * client's main thread.
         */
        void ProcessEvents();


        /**
         * Use this method to determine whether this application has full
         * capabilities.  Only one application (the first one started) can have
         * full capabilities.  If this is the first application started, this
         * method returns true.  When an application has full capabilities, 
         * it can initiate connections, as well as offer UI capabilities.
         */
        bool hasFullCapabilities();


        /**
         * This method returns true if the client has an active VPN
         * connection with a secure gateway.
         */
        bool isConnected(bool bSilent = false);


        /**
         * This method returns true if the client VPN is available for use.
         * If false is returned this means that VPN has been intentionally
         * disabled.  This would indicate a situation where other AnyConnect
         * services were in use but not VPN.
         */
        bool isAvailable();


        /**
         * This method returns true if the VPN service is available for
         * establishing VPN connections.
         */
        bool isVPNServiceAvailable();


        /**
         * This method returns true if the mode in which the client is
         * currently operating is enabled. For a list of all possible modes
         * of operation see the ::OperatingMode enum in api.h.
         */
        bool isOperatingMode(OperatingMode opMode);

        /**
         * This method returns a list of secure gateway host names found in an
         * AnyConnect profile.  If no profile is available, an empty
         * list is returned.
         */
        std::list<tstring> getHostNames();


        /**
         * This method returns any default Host name from User Preferences.
         *
         * A host can be returned here even if there are no profiles on the
         * system.  The host last connected to (via the connect method) is
         * returned by this method.
         *
         * If there is no previously connected-to host, the first host found
         * in an AnyConnect profile (if any) is returned.
         */
        tstring getDefaultHostName();


        /**
         * This method initiates a connection to the specified host.
         * The connection results in the presentation of authentication
         * credentials, as appropriate.  Any credentials returned by the secure
         * gateway are delivered via the #UserPromptCB method.
         *
         * See ConnectPromptInfo for more details on possible authentication
         * credentials.
         *
         * If the connection request is accepted, true is returned.  This does
         * not mean the connection succeeded.  If the connection succeeds, a
         * state of connect will be received via the #StateCB method.
         */
        bool connect(
            tstring host);

#if defined(HOST_DATA_SUPPORTED)
        bool connect(
            const IHostData& host);
#endif

        bool connect(
#if defined(HOST_DATA_SUPPORTED)
            const IHostData& host,
#else
            tstring host,
#endif
            unsigned int origin);

        /**
         * Use this method to change selected group after initial connection
         * request has been made and credentials were delivered. 
         *
         * Depending on secure gateway configuratiion, call to this method may
         * result in a new connection request and will update credentials 
         * required for the selected group. New credentials returned by the 
         * secure gateway are delivered via the #UserPromptCB method.
         */
        bool setNewTunnelGroup(const tstring & group);

        /**
         * Use this method to initiate a disconnect of the active VPN
         * connection.
         *
         * An indication of VPN disconnect is received via the #StateCB
         * method.
         */
        void disconnect();

        /**
        * Use this method to cancel the user authentication. VPN tunnel is not connected
        * at the moment. This function is used to cancel SSO authentication.
        *
        * An indication of VPN disconnect is received via the #StateCB
        * method.
        */
        void cancel();

        /**
         * This method triggers the retrieval of the current VPN state.
         * After the client is conected to the VPN service via the #attach
         * method, both the current state and any changes in state are
         * automatically delivered to the client.  In general, this method
         * should not be needed.
         *
         * ::VPNState is delivered via #StateCB method.
         */
        void getState();


        /**
         * This method triggers the retrieval of the current VPN statistics.
         * This allows an UI to notify the API that it is ready to receive 
         * statistics.
         *
         * ::VPNState is delivered via #StatsCB method.
         */
        void getStats();

        /**
         * This method resets current VPN statistics counters.
         */
        void resetStats();


        /**
         * This method activates the retrieval of VPN statistics and other
         * related data.  By default, VPNStats are automatically delivered
         * via the method #StatsCB.
         *
         * If the #stopStats method is called to stop the delivery of
         * statistics, this method can be called to resume delivery.  
         */
        void startStats();


        /**
         * This method stops the delivery of VPN statistics and
         * other related data.  By default, VPNStats are automatically
         * delivered.  This method disables delivery.
         *
         * The method #startStats can be called to resume the delivery of
         * statistics.
         */
        void stopStats();


        /**
         * This method directs where and how to export the statistics
         */
        void exportStats(const tstring &tstrFilePath);


        /**
         * Call this method after a #BannerCB has been received to indicate 
         * that the user response to the banner can now be read.
         *
         * \param bAccepted
         * indicates if the user accepted or declined the banner.
         */
        void setBannerResponse(bool bAccepted);

        /**
         * Call this method after a #PreConnectReminderCB has been received 
         * to indicate that user has acknowledged pre-connect reminder message.
         *
         * NOTE : Ignoring the response from user (for example, closing the modal
         *        dialog instead of clicking OK button). Old AnyConnect client (v3.1) 
         *        ignored the response too.
         */
        void setPreConnectReminderResponse();

        /*
         * Call this method after a #CertBlockedCB has been received to
         * indicate the user's response to the blocked untrusted VPN server
         * error message.
         *
         * \param bUnblock indicates if the user wants to disable the
         * preference to block untrusted servers
        */
        void setCertBlockedResponse(bool bUnblock);

        /*
         * Call this method after a #CertWarningCB has been received to
         * indicate the user's response to the server certificate error
         * warning
         *
         * \param bConnect indicates user wants to connect anyways
         * \param bImport inidicates user wants to permanently trust
         * the VPN server. This would result in no future certificate
         * error warning prompts. bImport is only valid if
         * bConnect is true and bAllowImport is true when a CertWarningCB
         * was given.
        */
        void setCertWarningResponse(bool bConnect, bool bImportCert);


        /**
         * Call this method to indicate that authentication credential
         * requests values solicited by the #UserPromptCB method can now
         * be read from the ConnectPromptInfo instance.
         */
        void UserSubmit();


        /**
         * Method for retrieving the currently available user preferences.
         * This method returns a instance of the class PreferenceInfo. The class
         * instance is a deep copy and therefore independent of any VPN API
         * object instances. It contains a variable number of Preference class
         * instance pointers. Each preference contains data identifying the
         * specific preference, its current value, etc. For a list of all
         * possible preferences see the PreferenceId enum in api.h. Note that
         * some of these preferences are not available to the user.
         *
         * @see PreferenceInfo
         */
        std::shared_ptr<PreferenceInfo> getPreferences();

        /**
        * Method for retrieving the current number of available user preferences.
        * This method provides an optimized means of determining if there are any available user
        * preferences. An application may have no need to retrieve the user preferences if there are
        * no user preferences available, and invoking getPreferences() incurs the cost of a deep
        * copy of the internal PreferenceInfo class instance, possibly causing many memory
        * allocations, even when there are no avaiable user preferences, which could result in poor
        * user interface responsiveness.
        * 
        * @see PreferenceInfo
        */
        unsigned int getPreferencesCount();

        /**
         * This method stores the current set values of the preferences to the 
         * preferences file(s).  This method is a counterpart to the 
         * getPreferences() method.
         */
        bool savePreferences(const std::shared_ptr<PreferenceInfo>& spPreferenceInfo);

        /**
         * This is called from the credential dialog in the GUI to get the correct
         * friendly name for the dialog title.
         */
        tstring getConnectHost();

        /**
         * This method sets the last VPN error seen during this connection
         * attempt for reporting purposes. This VPN error should be cleared for
         * each connection attempt.
         */
        void setLastVpnError(VPNError vpnError);


        /**
         * This method gets the last VPN error seen during this connection
         * attempt for reporting purposes. This VPN error should be cleared for
         * each connection attempt.
         */
        VPNError getLastVpnError();

        /**
        * This method indicates if a request to connect has been initiated and the SG is being
        * contacted. Note: the connect request is not active while waiting for the user to enter
        * credentials.
        */
        bool isConnectRequestActive();

    private:

        //
        //
        // Private Member Methods
        //
        //

        // Prevent copying by declaring but not defining copy constructor and operator= methods.
        //
        ClientIfc(const ClientIfc& other);
        ClientIfc& operator=(const ClientIfc& other);

#if defined(VPNAPI_EVENT_NOTIFICATION_SUPPORTED)
        virtual void EventNotificationInternalCB(
            const std::shared_ptr<CEventNotificationTlv>& spEventNtfctnTlv);
#endif

        using ClientIfcBase::ClientIfcTransmigration;

        //
        //
        // Private Member Data
        //
        //

        ClientIfcData* const m_pClientIfcData;
};

#endif //_CLIENTIFC_
