package org.wso2.carbon.device.mgt.ios.payload.operation;

import org.wso2.carbon.device.mgt.ios.payload.beans.ActionParameter;
import org.wso2.carbon.device.mgt.ios.payload.beans.AppLayerVPNMapping;
import org.wso2.carbon.device.mgt.ios.payload.beans.AppToPerAppVPNMapping;
import org.wso2.carbon.device.mgt.ios.payload.beans.AuthenticationMethod;
import org.wso2.carbon.device.mgt.ios.payload.beans.OnDemandRule;
import org.wso2.carbon.device.mgt.ios.payload.beans.PayloadOperation;
import org.wso2.carbon.device.mgt.ios.payload.beans.PerAppVPN;
import org.wso2.carbon.device.mgt.ios.payload.beans.SecurityAssociationParameters;
import org.wso2.carbon.device.mgt.ios.payload.beans.VPN;
import org.wso2.carbon.device.mgt.ios.payload.beans.VPNType;
import org.wso2.carbon.device.mgt.ios.payload.beans.VendorConfig;
import org.wso2.carbon.device.mgt.ios.payload.dto.PayloadOperationWrapper;
import org.wso2.carbon.device.mgt.ios.payload.dto.PayloadProperties;
import org.wso2.carbon.device.mgt.ios.payload.exception.PListException;
import org.wso2.carbon.device.mgt.ios.payload.exception.ProfileConfigurationException;
import org.wso2.carbon.device.mgt.ios.payload.util.OperationUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class VPNOperations {

    private static final String PAYLOAD_DISPLAY_NAME = "VPN Configurations";
    private static final String PAYLOAD_DESCRIPTION = "VPN Configurations for %s";
    private static final String USER_DEFINED_NAME = "UserDefinedName";
    private static final String IPV4 = "IPv4";
    private static final String OVERRIDE_PRIMARY = "OverridePrimary";
    private static final String VPN_TYPE = "VPNType";
    private static final String VPN_SUB_TYPE = "VPNSubType";
    private static final String ON_DEMAND_ENABLED = "OnDemandEnabled";
    private static final String ON_DEMAND_MATCH_DOMAINS_ALWAYS = "OnDemandMatchDomainsAlways";
    private static final String ON_DEMAND_MATCH_DOMAINS_NEVER = "OnDemandMatchDomainsNever";
    private static final String ON_DEMAND_MATCH_DOMAINS_ON_RETRY = "OnDemandMatchDomainsOnRetry";
    private static final String ACTION = "Action";
    private static final String ACTION_PARAMETERS = "ActionParameters";
    private static final String DOMAINS = "Domains";
    private static final String DOMAIN_ACTION = "DomainAction";
    private static final String REQUIRED_DNS_SERVERS = "RequiredDNSServers";
    private static final String REQUIRED_URL_STRING_PROBE = "RequiredURLStringProbe";
    private static final String DNS_DOMAIN_MATCH = "DNSDomainMatch";
    private static final String DNS_SERVER_ADDRESS_MATCH = "DNSServerAddressMatch";
    private static final String INTERFACE_TYPE_MATCH = "InterfaceTypeMatch";
    private static final String SSID_MATCH = "SSIDMatch";
    private static final String URL_STRING_PROBE = "URLStringProbe";
    private static final String ON_DEMAND_RULES = "OnDemandRules";
    private static final String VENDOR_CONFIG = "VendorConfig";
    private static final String AUTH_NAME = "AuthName";
    private static final String AUTH_PASSWORD = "AuthPassword";
    private static final String TOKEN_CARD = "TokenCard";
    private static final String COMM_REMOTE_ADDRESS = "CommRemoteAddress";
    private static final String AUTH_EAP_PLUGINS = "AuthEAPPlugins";
    private static final String EAP_RSA = "EAP-RSA";
    private static final String EAP = "EAP";
    private static final String AUTH_PROTOCOL = "AuthProtocol";
    private static final String CCPMPPE40_ENABLED = "CCPMPPE40Enabled";
    private static final String CCPMPPE128_ENABLED = "CCPMPPE128Enabled";
    private static final String CCP_ENABLED = "CCPEnabled";
    private static final String REMOTE_ADDRESS = "RemoteAddress";
    private static final String AUTHENTICATION_METHOD = "AuthenticationMethod";
    private static final String XAUTH_ENABLED = "XAuthEnabled";
    private static final String XAUTH_NAME = "XAuthName";
    private static final String LOCAL_IDENTIFIER = "LocalIdentifier";
    private static final String REMOTE_IDENTIFIER = "RemoteIdentifier";
    private static final String LOCAL_IDENTIFIER_TYPE = "LocalIdentifierType";
    private static final String KEY_ID = "KeyID";
    private static final String SHARED_SECRET = "SharedSecret";
    private static final String PAYLOAD_CERTIFICATE_UUID = "PayloadCertificateUUID";
    private static final String CERTIFICATE_TYPE = "CertificateType";
    private static final String PROMPT_FOR_VPN_PIN = "PromptForVPNPIN";
    private static final String PPP = "PPP";
    private static final String IP_SEC = "IPSec";
    private static final String IKEV2 = "IKEv2";
    private static final String EXTENDED_AUTH_ENABLED = "ExtendedAuthEnabled";
    private static final String DEAD_PEER_DETECTION_INTERVAL = "DeadPeerDetectionRate";
    private static final String SERVER_CERTIFICATE_COMMON_NAME = "ServerCertificateCommonName";
    private static final String TLS_MINIMUM_VERSION = "TLSMinimumVersion";
    private static final String TLS_MAXIMUM_VERSION = "TLSMaximumVersion";
    private static final String ENABLE_PFS = "EnablePFS";
    private static final String ENABLE_CERTIFICATE_REVOCATION_CHECK = "EnableCertificateRevocationCheck";
    private static final String SERVER_CERTIFICATE_ISSUER_COMMON_NAME = "ServerCertificateIssuerCommonName";
    private static final String IKE_SECURITY_ASSOCIATION_PARAMETERS = "IKESecurityAssociationParameters";
    private static final String CHILD_SECURITY_ASSOCIATION_PARAMETERS = "ChildSecurityAssociationParameters";
    private static final String ENCRYPTION_ALGORITHM = "EncryptionAlgorithm";
    private static final String INTEGRITY_ALGORITHM = "IntegrityAlgorithm";
    private static final String DIFFIE_HELLMAN_GROUP = "DiffieHellmanGroup";
    private static final String LIFE_TIME_IN_MINUTES = "LifeTimeInMinutes";
    private static final String INTERNAL_IP_SUBNET = "UseConfigurationAttributeInternalIPSubnet";
    private static final String DISABLE_MOBIKE = "DisableMOBIKE";
    private static final String DISABLE_REDIRECT = "DisableRedirect";
    private static final String NAT_KEEP_ALIVE_OFFLOAD_ENABLE = "NATKeepAliveOffloadEnable";
    private static final String NAT_KEEP_ALIVE_INTERVAL = "NATKeepAliveInterval";

    private static final String VPN_UUID = "VPNUUID";
    private static final String SAFARI_DOMAINS = "SafariDomains";
    private static final String ON_DEMAND_MATCH_APP_ENABLED = "OnDemandMatchAppEnabled";

    private static final String IDENTIFIER = "Identifier";
    private static final String APP_LAYER_VPN_MAPPING = "AppLayerVPNMapping";
    private static final String PASSWORD = "Password";

    private static final String PROXIES = "Proxies";
    private static final String HTTP_ENABLE = "HTTPEnable";
    private static final String HTTPS_ENABLE = "HTTPSEnable";

    private static int onDemandValue;

    public PayloadOperationWrapper createVPNPayload(VPN vpn) throws PListException,
            ProfileConfigurationException {

        PayloadProperties payloadProperties = generateVPNCommonElements(vpn,
                OperationUtils.getTenantNameFromOperationID(), OperationUtils.isPayloadRemoveDisallowedForTenant());

        vpn.validateRequest();

        Map<String, Object> commandMap = vpn.getCommandMap();
        commandMap.put(USER_DEFINED_NAME, vpn.getUserDefinedName());

        Map<String, Object> overridePrimaryMap = new HashMap<String, Object>();
        overridePrimaryMap.put(OVERRIDE_PRIMARY, vpn.getOverridePrimary());
        commandMap.put(IPV4, overridePrimaryMap);

        commandMap.put(VPN_TYPE, vpn.getVpnType().toString());

        if (vpn.getOnDemandEnabled()) {
            onDemandValue = 1;
            commandMap.put(ON_DEMAND_ENABLED, onDemandValue);
        } else {
            commandMap.put(ON_DEMAND_ENABLED, onDemandValue);
        }
        commandMap.put(ON_DEMAND_ENABLED, vpn.getOnDemandEnabled());
//        commandMap.put(ON_DEMAND_MATCH_DOMAINS_ALWAYS, vpn.getOnDemandMatchDomainsAlways());
//        commandMap.put(ON_DEMAND_MATCH_DOMAINS_NEVER, vpn.getOnDemandMatchDomainsNever());
//        commandMap.put(ON_DEMAND_MATCH_DOMAINS_ON_RETRY, vpn.getOnDemandMatchDomainsOnRetry());

        List<Map<String, Object>> onDemandRuleList = new ArrayList<Map<String, Object>>();

        if (vpn.getOnDemandRules() != null) {
            for(OnDemandRule onDemandRule : vpn.getOnDemandRules()) {

                Map<String, Object> onDemandRuleMap = new HashMap<String, Object>();
                onDemandRuleMap.put(ACTION, onDemandRule.getOnDemandRuleAction().toString());

                List<Map<String, Object>> actionParameterList = new ArrayList<Map<String, Object>>();

                if (onDemandRule.getActionParameters() != null) {
                    for (ActionParameter actionParameter : onDemandRule.getActionParameters()) {
                        Map<String, Object> actionParameterMapEntry = new HashMap<String, Object>();
                        actionParameterMapEntry.put(DOMAINS, actionParameter.getDomains());
                        actionParameterMapEntry.put(DOMAIN_ACTION, actionParameter.getDomainAction().toString());
                        actionParameterMapEntry.put(REQUIRED_DNS_SERVERS, actionParameter.getRequiredDNSServers());
                        actionParameterMapEntry.put(REQUIRED_URL_STRING_PROBE,
                                actionParameter.getRequiredURLStringProbe());

                        actionParameterList.add(actionParameterMapEntry);
                    }
                }

                onDemandRuleMap.put(ACTION_PARAMETERS, actionParameterList);
                onDemandRuleMap.put(DNS_DOMAIN_MATCH, onDemandRule.getDNSDomainMatch());
                onDemandRuleMap.put(DNS_SERVER_ADDRESS_MATCH, onDemandRule.getDNSServerAddressMatch());
                onDemandRuleMap.put(INTERFACE_TYPE_MATCH, onDemandRule.getInterfaceTypeMatch().toString());
                onDemandRuleMap.put(SSID_MATCH, onDemandRule.getSSIDMatch());
                onDemandRuleMap.put(URL_STRING_PROBE, onDemandRule.getURLStringProbe());

                onDemandRuleList.add(onDemandRuleMap);
            }

            commandMap.put(ON_DEMAND_RULES, onDemandRuleList);
        }

        Map<String, Object> vendorConfigs = new HashMap<String, Object>();

//        if (vpn.getVendorConfigs() != null) {
//            // only pick one config if available
//            VendorConfig vendorConfig = vpn.getVendorConfigs().get(0);
//
//        }
        commandMap.put(VENDOR_CONFIG, vendorConfigs);

        if (vpn.getPpp() != null && (vpn.getVpnType() == VPNType.PPTP || vpn.getVpnType() == VPNType.L2TP)) {
            Map<String, Object> pppMap = new HashMap<String, Object>();
            pppMap.put(AUTH_NAME, vpn.getPpp().getAuthName());
            pppMap.put(COMM_REMOTE_ADDRESS, vpn.getPpp().getCommRemoteAddress());

            if (vpn.getPpp().getTokenCard() != null && vpn.getPpp().getTokenCard().booleanValue()) {
                pppMap.put(AUTH_PASSWORD, vpn.getPpp().getAuthPassword());
            }

            if (vpn.getVpnType() == VPNType.L2TP && vpn.getPpp().getTokenCard() != null) {
                pppMap.put(TOKEN_CARD, vpn.getPpp().getTokenCard());
            }

            if (vpn.getVpnType() == VPNType.PPTP) {
                pppMap.put(CCPMPPE40_ENABLED, vpn.getPpp().getCCPMPPE40Enabled());
                pppMap.put(CCPMPPE128_ENABLED, vpn.getPpp().getCCPMPPE128Enabled());
                pppMap.put(CCP_ENABLED, vpn.getPpp().getCCPEnabled());
            }

            if (vpn.getPpp().getRSASecureID() != null && vpn.getPpp().getRSASecureID().booleanValue()) {
                List<String> eapPluginList = new ArrayList<String>();
                eapPluginList.add(EAP_RSA);
                pppMap.put(AUTH_EAP_PLUGINS, eapPluginList);

                List<String> eapList = new ArrayList<String>();
                eapList.add(EAP);
                pppMap.put(AUTH_PROTOCOL, eapList);
            }

            commandMap.put(PPP, pppMap);
        }

        if (vpn.getIpSec() != null && vpn.getVpnType() == VPNType.IPSec) {
            Map<String, Object> ipSecMap = new HashMap<String, Object>();
            ipSecMap.put(REMOTE_ADDRESS, vpn.getIpSec().getRemoteAddress());

            if(vpn.getIpSec().getAuthenticationMethod() != null) {
                ipSecMap.put(AUTHENTICATION_METHOD, vpn.getIpSec().getAuthenticationMethod().toString());
            }

            if(vpn.getIpSec().getXAuthEnabled() != null) {
                ipSecMap.put(XAUTH_ENABLED, (vpn.getIpSec().getXAuthEnabled()));
            }

            ipSecMap.put(XAUTH_NAME, vpn.getIpSec().getXAuthName());

            if (vpn.getIpSec().getAuthenticationMethod() == AuthenticationMethod.SharedSecret) {
                ipSecMap.put(LOCAL_IDENTIFIER, vpn.getIpSec().getLocalIdentifier());
                ipSecMap.put(LOCAL_IDENTIFIER_TYPE, KEY_ID);
                ipSecMap.put(SHARED_SECRET, vpn.getIpSec().getSharedSecret().getBytes());
            }

            if (vpn.getIpSec().getAuthenticationMethod() == AuthenticationMethod.Certificate) {
                ipSecMap.put(PAYLOAD_CERTIFICATE_UUID, vpn.getIpSec().getPayloadCertificateUUID());
            }

            ipSecMap.put(PROMPT_FOR_VPN_PIN, vpn.getIpSec().getPromptForVPNPIN());

            commandMap.put(IP_SEC, ipSecMap);
        }

        if (vpn.getPulseSecure() != null && vpn.getVpnType() == VPNType.PulseSecure) {
            commandMap.remove(VPN_TYPE);
            commandMap.put(VPN_TYPE, VPNType.VPN.toString());
            commandMap.put(VPN_SUB_TYPE, "net.pulsesecure.PulseSecure.vpnplugin");

            // TODO: Get proxy config from UI
            Map<String, Object> proxyConfig = new HashMap<String, Object>();
            proxyConfig.put(HTTP_ENABLE, 0);
            proxyConfig.put(HTTPS_ENABLE, 0);
            commandMap.put(PROXIES, proxyConfig);

            Map<String, Object> pulseSecureMap = new HashMap<String, Object>();
            pulseSecureMap.put(REMOTE_ADDRESS, vpn.getPulseSecure().getRemoteAddress());
            pulseSecureMap.put(AUTHENTICATION_METHOD, PASSWORD);

            commandMap.put(VPNType.VPN.toString(), pulseSecureMap);
        }

        if (vpn.getIkEv2() != null && vpn.getVpnType() == VPNType.IKEv2) {
            Map<String, Object> ikeV2Map = new HashMap<String, Object>();
            ikeV2Map.put(REMOTE_ADDRESS, vpn.getIkEv2().getRemoteAddress());

            if(vpn.getIkEv2().getLocalIdentifier() != null) {
                ikeV2Map.put(LOCAL_IDENTIFIER, vpn.getIkEv2().getLocalIdentifier().toString());
            }

            if(vpn.getIkEv2().getRemoteIdentifier() != null) {
                ikeV2Map.put(REMOTE_IDENTIFIER, vpn.getIkEv2().getRemoteIdentifier().toString());
            }

            if(vpn.getIkEv2().getAuthenticationMethod() != null) {
                ikeV2Map.put(AUTHENTICATION_METHOD, vpn.getIkEv2().getAuthenticationMethod().toString());
            }

            ikeV2Map.put(PAYLOAD_CERTIFICATE_UUID, vpn.getIkEv2().getPayloadCertificateUUID());

            if (vpn.getIkEv2().getCertificateType() != null){
                ikeV2Map.put(CERTIFICATE_TYPE, vpn.getIkEv2().getCertificateType());
            }

            ikeV2Map.put(SHARED_SECRET, vpn.getIkEv2().getSharedSecret());
            ikeV2Map.put(EXTENDED_AUTH_ENABLED, vpn.getIkEv2().getExtendedAuthEnabled());
            ikeV2Map.put(AUTH_NAME, vpn.getIkEv2().getAuthName());
            ikeV2Map.put(AUTH_PASSWORD, vpn.getIkEv2().getAuthPassword());

            if(vpn.getIkEv2().getDeadPeerDetectionInterval() != null) {
                ikeV2Map.put(DEAD_PEER_DETECTION_INTERVAL, vpn.getIkEv2().getDeadPeerDetectionInterval().toString());
            }

            ikeV2Map.put(SERVER_CERTIFICATE_ISSUER_COMMON_NAME, vpn.getIkEv2().getServerCertificateIssuerCommonName());
            ikeV2Map.put(SERVER_CERTIFICATE_COMMON_NAME, vpn.getIkEv2().getServerCertificateCommonName());
            ikeV2Map.put(TLS_MINIMUM_VERSION, vpn.getIkEv2().getTLSMinimumVersion());
            ikeV2Map.put(TLS_MAXIMUM_VERSION, vpn.getIkEv2().getTLSMaximumVersion());
            ikeV2Map.put(NAT_KEEP_ALIVE_OFFLOAD_ENABLE, vpn.getIkEv2().getNATKeepAliveOffloadEnable());
            ikeV2Map.put(NAT_KEEP_ALIVE_INTERVAL, vpn.getIkEv2().getNATKeepAliveInterval());
            ikeV2Map.put(ENABLE_PFS, vpn.getIkEv2().getEnablePFS());
            ikeV2Map.put(ENABLE_CERTIFICATE_REVOCATION_CHECK, vpn.getIkEv2().getEnableCertificateRevocationCheck());

            SecurityAssociationParameters securityAssociationParameters = vpn.getIkEv2().
                    getIKESecurityAssociationParameters();

            if (securityAssociationParameters != null) {
                ikeV2Map.put(IKE_SECURITY_ASSOCIATION_PARAMETERS, generateSecurityAssociationParameters(
                        vpn.getIkEv2().getIKESecurityAssociationParameters()));
            }

            SecurityAssociationParameters childSecurityAssociationParameters = vpn.getIkEv2().
                    getChildSecurityAssociationParameters();

            if (childSecurityAssociationParameters != null) {
                ikeV2Map.put(CHILD_SECURITY_ASSOCIATION_PARAMETERS, generateSecurityAssociationParameters(
                        vpn.getIkEv2().getChildSecurityAssociationParameters()));
            }

            commandMap.put(IKEV2, ikeV2Map);
        }

        List<Object> payloadContent = new ArrayList<Object>();
        payloadContent.add(commandMap);

        PayloadOperationWrapper payloadOperationWrapper = new PayloadOperationWrapper();
        payloadOperationWrapper.setPayload(payloadContent);
        payloadOperationWrapper.setPayloadProperties(payloadProperties);

        return payloadOperationWrapper;
    }

    private Map<String, Object> generateSecurityAssociationParameters
            (SecurityAssociationParameters securityAssociationParameters) {

        Map<String, Object> parameterMap = new HashMap<String, Object>();

        if(securityAssociationParameters.getEncryptionAlgorithm() != null) {
            parameterMap.put(ENCRYPTION_ALGORITHM, securityAssociationParameters.getEncryptionAlgorithm().getValue());
        }

        if(securityAssociationParameters.getIntegrityAlgorithm() != null) {
            parameterMap.put(INTEGRITY_ALGORITHM, securityAssociationParameters.getIntegrityAlgorithm().getValue());
        }

        parameterMap.put(DIFFIE_HELLMAN_GROUP, securityAssociationParameters.getDiffieHellmanGroup());
        parameterMap.put(LIFE_TIME_IN_MINUTES, securityAssociationParameters.getLifeTimeInMinutes());
        parameterMap.put(INTERNAL_IP_SUBNET, securityAssociationParameters.getUseConfigurationAttributeInternalIPSubnet());
        parameterMap.put(DISABLE_MOBIKE, securityAssociationParameters.getDisableMOBIKE());
        parameterMap.put(DISABLE_REDIRECT, securityAssociationParameters.getDisableRedirect());
        parameterMap.put(NAT_KEEP_ALIVE_OFFLOAD_ENABLE, securityAssociationParameters.getNATKeepAliveOffloadEnable());
        parameterMap.put(NAT_KEEP_ALIVE_INTERVAL, securityAssociationParameters.getNATKeepAliveInterval());

        return parameterMap;
    }

    public PayloadOperationWrapper createPerAppVPNPayload(PerAppVPN perAppVPN) throws PListException,
            ProfileConfigurationException {

        PayloadProperties payloadProperties = generatePerAppVPNCommonElements(perAppVPN,
                OperationUtils.getTenantNameFromOperationID(), OperationUtils.isPayloadRemoveDisallowedForTenant());

        perAppVPN.validateRequest();

        Map<String, Object> commandMap = perAppVPN.getCommandMap();
        commandMap.put(VPN_UUID, perAppVPN.getVPNUUID());
        commandMap.put(SAFARI_DOMAINS, perAppVPN.getSafariDomains());
        commandMap.put(ON_DEMAND_MATCH_APP_ENABLED, perAppVPN.getOnDemandMatchAppEnabled());

        List<Object> payloadContent = new ArrayList<Object>();
        payloadContent.add(commandMap);

        PayloadOperationWrapper payloadOperationWrapper = new PayloadOperationWrapper();
        payloadOperationWrapper.setPayload(payloadContent);
        payloadOperationWrapper.setPayloadProperties(payloadProperties);

        return payloadOperationWrapper;
    }

    public PayloadOperationWrapper createAppToPerAppVPNMappingPayload(AppToPerAppVPNMapping appToPerAppVPNMapping) throws PListException,
            ProfileConfigurationException {

        PayloadProperties payloadProperties = generateAppToPerAppVPNMappingCommonElements(appToPerAppVPNMapping,
                OperationUtils.getTenantNameFromOperationID(), OperationUtils.isPayloadRemoveDisallowedForTenant());

        appToPerAppVPNMapping.validateRequest();

        Map<String, Object> commandMap = appToPerAppVPNMapping.getCommandMap();

        List<Map<String, Object>> appLayerVPNMappingList = new ArrayList<Map<String, Object>>();

        for(AppLayerVPNMapping appLayerVPNMapping : appToPerAppVPNMapping.getAppLayerVPNMappings()) {
            Map<String, Object> appLayerVPNMappingMap = new HashMap<String, Object>();
            appLayerVPNMappingMap.put(IDENTIFIER, appLayerVPNMapping.getIdentifier());
            appLayerVPNMappingMap.put(VPN_UUID, appLayerVPNMapping.getVPNUUID());

            appLayerVPNMappingList.add(appLayerVPNMappingMap);
        }

        commandMap.put(APP_LAYER_VPN_MAPPING, appLayerVPNMappingList);

        List<Object> payloadContent = new ArrayList<Object>();
        payloadContent.add(commandMap);

        PayloadOperationWrapper payloadOperationWrapper = new PayloadOperationWrapper();
        payloadOperationWrapper.setPayload(payloadContent);
        payloadOperationWrapper.setPayloadProperties(payloadProperties);

        return payloadOperationWrapper;
    }

    private PayloadProperties generateVPNCommonElements(VPN vpn, String tenantName,
                                        boolean payloadRemoveDisallowed) {

        PayloadProperties payloadProperties = new PayloadProperties();
        payloadProperties.setTenantName(tenantName);
        payloadProperties.setPayloadType(PayloadOperation.PayloadType.VPN.getPayloadType());
        payloadProperties.setPayloadIdentifier(vpn.getUUID());
        payloadProperties.setPayloadDisplayName(PAYLOAD_DISPLAY_NAME);
        payloadProperties.setPayloadDescription(String.format(PAYLOAD_DESCRIPTION, tenantName));
        payloadProperties.setPayloadRemoveDisallowed(payloadRemoveDisallowed);

        vpn.populateCommandPayloadElements(payloadProperties);

        return payloadProperties;
    }

    private PayloadProperties generatePerAppVPNCommonElements(PerAppVPN perAppVPN, String tenantName,
                                           boolean payloadRemoveDisallowed) {

        PayloadProperties payloadProperties = new PayloadProperties();
        payloadProperties.setTenantName(tenantName);
        payloadProperties.setPayloadType(PayloadOperation.PayloadType.PER_APP_VPN.getPayloadType());
        payloadProperties.setPayloadIdentifier(perAppVPN.getUUID());
        payloadProperties.setPayloadDisplayName(PAYLOAD_DISPLAY_NAME);
        payloadProperties.setPayloadDescription(String.format(PAYLOAD_DESCRIPTION, tenantName));
        payloadProperties.setPayloadRemoveDisallowed(payloadRemoveDisallowed);

        perAppVPN.populateCommandPayloadElements(payloadProperties);

        return payloadProperties;
    }

    private PayloadProperties generateAppToPerAppVPNMappingCommonElements(AppToPerAppVPNMapping appToPerAppVPNMapping,
                                                             String tenantName, boolean payloadRemoveDisallowed) {

        PayloadProperties payloadProperties = new PayloadProperties();
        payloadProperties.setTenantName(tenantName);
        payloadProperties.setPayloadType(PayloadOperation.PayloadType.APP_TO_PER_APP_VPN_MAPPING.getPayloadType());
        payloadProperties.setPayloadIdentifier(appToPerAppVPNMapping.getUUID());
        payloadProperties.setPayloadDisplayName(PAYLOAD_DISPLAY_NAME);
        payloadProperties.setPayloadDescription(String.format(PAYLOAD_DESCRIPTION, tenantName));
        payloadProperties.setPayloadRemoveDisallowed(payloadRemoveDisallowed);

        appToPerAppVPNMapping.populateCommandPayloadElements(payloadProperties);

        return payloadProperties;
    }
}
