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

import org.wso2.carbon.device.mgt.ios.payload.beans.EncryptionType;
import org.wso2.carbon.device.mgt.ios.payload.beans.PayloadOperation;
import org.wso2.carbon.device.mgt.ios.payload.beans.ProxyType;
import org.wso2.carbon.device.mgt.ios.payload.beans.WIFI;
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 WIFIOperations {

    private static final String PAYLOAD_DISPLAY_NAME = "WIFI Configurations";
    private static final String PAYLOAD_DESCRIPTION = "WIFI Configurations for %s";
    private static final String SSID = "SSID_STR";
    private static final String HIDDEN_NETWORK = "HIDDEN_NETWORK";
    private static final String AUTO_JOIN = "AutoJoin";
    private static final String ENCRYPTION_TYPE = "EncryptionType";
    private static final String IS_HOTSPOT = "IsHotspot";
    private static final String DOMAIN_NAME = "DomainName";
    private static final String SERVICE_PROVIDER_ROAMING_ENABLED = "ServiceProviderRoamingEnabled";
    private static final String DISPLAYED_OPERATOR_NAME = "DisplayedOperatorName";
    private static final String PROXY_TYPE = "ProxyType";
    private static final String ROAMING_CONSORTIUM_OIS = "RoamingConsortiumOIs";
    private static final String NAI_REAL_NAMES = "NAIRealmNames";
    private static final String MCC_AND_MNCS = "MCCAndMNCs";

    private static final String PASSWORD = "Password";
    private static final String PAYLOAD_CERTIFICATE_UUID = "PayloadCertificateUUID";
    private static final String EAP_CLIENT_CONFIGURATION = "EAPClientConfiguration";
    private static final String USERNAME = "UserName";
    private static final String ACCEPT_EAP_TYPES = "AcceptEAPTypes";
    private static final String USER_PASSWORD = "UserPassword";
    private static final String ONE_TIME_PASSWORD = "OneTimePassword";
    private static final String PAYLOAD_CERTIFICATE_ANCHOR_UUID = "PayloadCertificateAnchorUUID";
    private static final String TLS_TRUSTED_SERVER_NAMES = "TLSTrustedServerNames";
    private static final String TLS_ALLOW_TRUST_EXCEPTIONS = "TLSAllowTrustExceptions";
    private static final String TLS_CERTIFICATE_IS_REQUIRED = "TLSCertificateIsRequired";
    private static final String TTLS_INNER_AUTHENTICATION = "TTLSInnerAuthentication";
    private static final String OUTER_IDENTITY = "OuterIdentity";
    private static final String EAP_FAST_USE_PAC = "EAPFASTUsePAC";
    private static final String EAP_FAST_PROVISION_PAC = "EAPFASTProvisionPAC";
    private static final String EAP_FAST_PROVISION_PAC_ANONYMOUSLY = "EAPFASTProvisionPACAnonymously";
    private static final String EAP_SIM_NUMBER_OF_RANDS = "EAPSIMNumberOfRANDs";
    private static final String PROXY_SERVER = "ProxyServer";
    private static final String PROXY_PORT = "ProxyPort";
    private static final String PROXY_USERNAME = "ProxyUsername";
    private static final String PROXY_PASSWORD = "ProxyPassword";
    private static final String PROXY_PA_CURL = "ProxyPACURL";
    private static final String PROXY_PAC_FALLBACK_ALLOWED = "ProxyPACFallbackAllowed";

    public PayloadOperationWrapper createWIFIPayload(WIFI wifi) throws PListException,
            ProfileConfigurationException {

        PayloadProperties payloadProperties = generateCommonElements(wifi,
                OperationUtils.getTenantNameFromOperationID(), OperationUtils.isPayloadRemoveDisallowedForTenant());

        wifi.validateRequest();

        Map<String, Object> wifiMap = wifi.getCommandMap();
        wifiMap.put(SSID, wifi.getSSID());
        wifiMap.put(HIDDEN_NETWORK, wifi.getHiddenNetwork());
        wifiMap.put(AUTO_JOIN, wifi.getAutoJoin());

        if(wifi.getEncryptionType() != null) {
            wifiMap.put(ENCRYPTION_TYPE, wifi.getEncryptionType().toString());
        }

        wifiMap.put(IS_HOTSPOT, wifi.getHotspot());
        wifiMap.put(DOMAIN_NAME, wifi.getDomainName());
        wifiMap.put(SERVICE_PROVIDER_ROAMING_ENABLED, wifi.getServiceProviderRoamingEnabled());
        wifiMap.put(DISPLAYED_OPERATOR_NAME, wifi.getDisplayedOperatorName());

        if(wifi.getProxyType() != null) {
            wifiMap.put(PROXY_TYPE, wifi.getProxyType().toString());
        }

        wifiMap.put(ROAMING_CONSORTIUM_OIS, wifi.getRoamingConsortiumOIs());
        wifiMap.put(NAI_REAL_NAMES, wifi.getNAIRealmNames());
        wifiMap.put(MCC_AND_MNCS, wifi.getMCCAndMNCs());

        if (wifi.getEncryptionType() == EncryptionType.WEP || wifi.getEncryptionType() == EncryptionType.WPA
                || wifi.getEncryptionType() == EncryptionType.Any) {

            Map<String, Object> eapClientConfiguration = new HashMap<String, Object>();
            eapClientConfiguration.put(USERNAME, wifi.getClientConfiguration().getUsername());
            eapClientConfiguration.put(ACCEPT_EAP_TYPES, wifi.getClientConfiguration().getAcceptEAPTypes());
            eapClientConfiguration.put(USER_PASSWORD, wifi.getClientConfiguration().getUserPassword());
            eapClientConfiguration.put(ONE_TIME_PASSWORD, wifi.getClientConfiguration().getOneTimePassword());
            eapClientConfiguration.put(PAYLOAD_CERTIFICATE_ANCHOR_UUID,
                    wifi.getClientConfiguration().getPayloadCertificateAnchorUUID());
            eapClientConfiguration.put(TLS_TRUSTED_SERVER_NAMES,
                    wifi.getClientConfiguration().getTLSTrustedServerNames());
            eapClientConfiguration.put(TLS_ALLOW_TRUST_EXCEPTIONS,
                    wifi.getClientConfiguration().getTLSAllowTrustExceptions());
            eapClientConfiguration.put(TLS_CERTIFICATE_IS_REQUIRED,
                    wifi.getClientConfiguration().getTLSCertificateIsRequired());
            eapClientConfiguration.put(TTLS_INNER_AUTHENTICATION,
                    wifi.getClientConfiguration().getTTLSInnerAuthentication());
            eapClientConfiguration.put(OUTER_IDENTITY, wifi.getClientConfiguration().getOuterIdentity());

            //EAP-Fast Support
            eapClientConfiguration.put(EAP_FAST_USE_PAC, wifi.getClientConfiguration().getEAPFASTUsePAC());
            eapClientConfiguration.put(EAP_FAST_PROVISION_PAC, wifi.getClientConfiguration().getEAPFASTProvisionPAC());
            eapClientConfiguration.put(EAP_FAST_PROVISION_PAC_ANONYMOUSLY,
                    wifi.getClientConfiguration().getEAPFASTProvisionPACAnonymously());
            eapClientConfiguration.put(EAP_SIM_NUMBER_OF_RANDS, wifi.getClientConfiguration().getEAPSIMNumberOfRANDs());

            if (!wifi.getClientConfiguration().getAcceptEAPTypes().isEmpty()) {
                wifiMap.put(EAP_CLIENT_CONFIGURATION, eapClientConfiguration);
            }

            wifiMap.put(PASSWORD, wifi.getPassword());
            wifiMap.put(PAYLOAD_CERTIFICATE_UUID, wifi.getPayloadCertificateUUID());
        }

        if (wifi.getProxyType() == ProxyType.Manual) {

            wifiMap.put(PROXY_SERVER, wifi.getProxyServer());
            wifiMap.put(PROXY_PORT, wifi.getProxyPort());
            wifiMap.put(PROXY_USERNAME, wifi.getProxyUsername());
            wifiMap.put(PROXY_PASSWORD, wifi.getProxyPassword());
            wifiMap.put(PROXY_PA_CURL, wifi.getProxyPACURL());
            wifiMap.put(PROXY_PAC_FALLBACK_ALLOWED, wifi.getProxyPACFallbackAllowed());
        }

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

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

        return payloadOperationWrapper;
    }

    private PayloadProperties generateCommonElements(WIFI wifi, String tenantName,
                                        boolean payloadRemoveDisallowed) {

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

        wifi.populateCommandPayloadElements(payloadProperties);

        return payloadProperties;
    }

}
