/**************************************************************************
*   Copyright (c) 2008, 2022-2024 Cisco Systems, Inc.
*   All Rights Reserved. Cisco Highly Confidential.
***************************************************************************
*
*   File:   PromptEntryBase.h
*   Date:   01/2008
*
***************************************************************************
*   Prompt Entry base class implementation for the Client API.
***************************************************************************/

#ifndef _PROMPTENTRYBASE_
#define _PROMPTENTRYBASE_


#include "api.h"
#include <list>
#include <unordered_set>


#define PROMPT_ENTRY_VALUE_TRUE  _T("true")
#define PROMPT_ENTRY_VALUE_FALSE  _T("false")

class VPN_VPNAPI PromptEntryBase
{
public:

    bool setValue(const tstring& value);
    bool clearValue();

    const tstring &getPromptName() const;

    const tstring &getPromptLabel() const;

    bool isEnabled() const;

    void setEnabled(bool bIsEnabled);

    bool isVisible() const;

    void setVisible(bool bIsVisible);

    // if this is a PromptEntry that has a list of values
    // (e.g. combo box style) the default will be to mark it as a group
    // combo.  This method allows the group designation to be set directly.
    //
    void setEntryGroup(bool bIsEntryGroup);


    PromptEntryBase(tstring PromptName,
                    tstring PromptLabel,
                    PromptType promptType = Prompt_Input,
                    const tstring& DefaultValue = EmptyString,
                    ApiStringMap LabelValues = EmptyLabelValues);


    void setPromptLabel(tstring label);

    // In cases of prompt types with options (checkbox, combobox),
    // this will return the translated label (of the option).
    const tstring &getValue() const;

    // this function returns the internal representation of the value
    const tstring &getTrueValue() const;

    const std::list<tstring> &getValueOptions() const;

    bool isEntryGroup() const;

    bool isReadOnly() const;

    PromptType getPromptType() const;

    size_t GetGroupAttributesCount();


    virtual ~PromptEntryBase();

    static const tstring EmptyString;

    static const std::list<tstring> EmptyList;

    static const ApiStringMap EmptyLabelValues;

    // Deep Copy Assignment Operator
    //
    PromptEntryBase& operator=(const PromptEntryBase& existingEntry)
    {
        return deepCopy(existingEntry);
    }

    // Deep Copy Constructor
    //
    explicit PromptEntryBase(const PromptEntryBase& existingEntry)
    {
        deepCopy(existingEntry);
    }


private:

    PromptEntryBase& deepCopy(const PromptEntryBase& existingEntry);

    tstring ms_PromptName;
    tstring ms_PromptLabel;
    PromptType me_PromptType;
    tstring ms_Value;
    ApiStringMap msm_LabelValueMap;
    std::list<tstring> mls_ValueOptions;
    bool mb_IsEntryGroup;
    bool mb_Enabled;
    bool mb_Visible;

public:

    class GroupAttributes
    {
    public:
        GroupAttributes() :
            CredRequired(true),
            UsesSDIAuth(false),
            UsernameEditable(true),
            SecondaryUsernameEditable(true),
            UsesSecondaryAuth(false)
        {
        }

        // Deep Copy Constructor
        //
        explicit GroupAttributes(
            const GroupAttributes& existingGroupAttr)
        {
            deepCopy(existingGroupAttr);
        }

        // Deep Copy Assignment Operator
        //
        GroupAttributes& operator=(
            const GroupAttributes& existingGroupAttr)
        {
            return deepCopy(existingGroupAttr);
        }

        bool CredRequired;
        bool UsesSDIAuth;
        bool UsernameEditable;
        tstring Username;
        bool SecondaryUsernameEditable;
        tstring SecondaryUsername;
        bool UsesSecondaryAuth;

    private:
        GroupAttributes& deepCopy(const GroupAttributes& existingGroupAttr)
        {
            if (std::addressof(existingGroupAttr) != this)
            {
                CredRequired = existingGroupAttr.CredRequired;
                UsesSDIAuth = existingGroupAttr.UsesSDIAuth;
                UsernameEditable = existingGroupAttr.UsernameEditable;
                Username = existingGroupAttr.Username.c_str();
                SecondaryUsernameEditable = existingGroupAttr.SecondaryUsernameEditable;
                SecondaryUsername = existingGroupAttr.SecondaryUsername.c_str();
                UsesSecondaryAuth = existingGroupAttr.UsesSecondaryAuth;
            }
            return *this;
        }
    };

    class SingleAttributes
    {
    public:
        SingleAttributes() :
            SecondaryAuthEntry(false),
            SSOTimeoutSeconds(0),
            SSOIsExternalBrowser(false)
        {
        }

        // Deep Copy Constructor
        //
        explicit SingleAttributes(
            const SingleAttributes& existingSingleAttr)
        {
            deepCopy(existingSingleAttr);
        }

        // Deep Copy Assignment Operator
        //
        SingleAttributes& operator=(
            const SingleAttributes& existingSingleAttr)
        {
            return deepCopy(existingSingleAttr);
        }

        bool SecondaryAuthEntry;
        tstring SSOURL;
        tstring SSOFinalURL;
        tstring SSOTokenCookieName;
        tstring SSOErrorCookieName;
        unsigned int SSOTimeoutSeconds;
        tstring SSOUserAgent;
        bool SSOIsExternalBrowser;
        std::unordered_set<tstring> SSOClientCertReqIgnoredFqdns;

    private:
        SingleAttributes& deepCopy(const SingleAttributes& existingSingleAttr)
        {
            if (std::addressof(existingSingleAttr) != this)
            {
                SecondaryAuthEntry = existingSingleAttr.SecondaryAuthEntry;
                SSOURL = existingSingleAttr.SSOURL.c_str();
                SSOFinalURL = existingSingleAttr.SSOFinalURL.c_str();
                SSOTokenCookieName = existingSingleAttr.SSOTokenCookieName.c_str();
                SSOErrorCookieName = existingSingleAttr.SSOErrorCookieName.c_str();
                SSOTimeoutSeconds = existingSingleAttr.SSOTimeoutSeconds;
                SSOUserAgent = existingSingleAttr.SSOUserAgent.c_str();
                SSOIsExternalBrowser = existingSingleAttr.SSOIsExternalBrowser;
                for (const auto& fqdn : existingSingleAttr.SSOClientCertReqIgnoredFqdns)
                {
                    SSOClientCertReqIgnoredFqdns.insert(fqdn.c_str());
                }
            }
            return *this;
        }
    };

    typedef std::map<tstring, GroupAttributes> GroupAttributesMap;

    const GroupAttributes& getGroupAttributes(const tstring& group) const;
    void setGroupAttributesMap(const GroupAttributesMap& groupAttributesMap);

    const SingleAttributes& getSingleAttributes() const;
    void setSingleAttributes(const SingleAttributes& singleAttributes);

private:

    void copyGroupAttributesMap (const GroupAttributesMap &srcMap,
                                 GroupAttributesMap &dstMap);

    static const GroupAttributes DefaultGroupAttributes;
    GroupAttributesMap m_GroupAttributesMap;
    SingleAttributes m_SingleAttributes;
};


#endif // _PROMPTENTRYBASE_
