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

import org.wso2.carbon.device.mgt.ios.payload.beans.APNConfig;
import org.wso2.carbon.device.mgt.ios.payload.beans.APNConfiguration;
import org.wso2.carbon.device.mgt.ios.payload.beans.Cellular;
import org.wso2.carbon.device.mgt.ios.payload.beans.LegacyAPNConfiguration;
import org.wso2.carbon.device.mgt.ios.payload.beans.PayloadOperation;
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 CellularOperations {

    public static final String ATTACH_APN_NAME = "Name";
    public static final String APN_NAME = "apn";
    public static final String DEFAULT_DOMAIN_NAME = "DefaultsDomainName";
    public static final String COM_APPLE_MANAGED_CARRIER = "com.apple.managedCarrier";
    public static final String AUTHENTICATION_TYPE = "AuthenticationType";
    public static final String USERNAME = "Username";
    public static final String PASSWORD = "Password";
    public static final String APN_USERNAME = "username";
    public static final String APN_PASSWORD = "password";
    public static final String ATTACH_APN = "AttachAPN";
    public static final String PROXY_SERVER = "ProxyServer";
    public static final String PROXY_PORT = "ProxyPort";
    public static final String APN_PROXY_SERVER = "proxy";
    public static final String APN_PROXY_PORT = "proxyPort";
    public static final String APN_ARRAY = "APNs";
    public static final String APN_ARRAY_LEGACY = "apns";
    public static final String DEFAULTS_DATA = "DefaultsData";
    private static final String PAYLOAD_DISPLAY_NAME = "Cellular Configurations";
    private static final String PAYLOAD_DESCRIPTION = "Cellular Configurations for %s";
    private static final String APN_PAYLOAD_DISPLAY_NAME = "APN Configurations";
    private static final String APN_PAYLOAD_DESCRIPTION = "APN Configurations for %s";
    public static final String CELLULAR_PAYLOAD_UUID = "CellularOperationUUID";

    public PayloadOperationWrapper createCellularPayload(Cellular cellular) throws PListException,
            ProfileConfigurationException {

        PayloadProperties payloadProperties = generateCommonElementsCellular(cellular,
                OperationUtils.getTenantNameFromOperationID(), OperationUtils.isPayloadRemoveDisallowedForTenant());

        cellular.validateRequest();

        Map<String, Object> attachAPNMap = new HashMap<String, Object>();
        attachAPNMap.put(ATTACH_APN_NAME, cellular.getAttachAPNName());

        if(cellular.getAuthenticationType() != null) {
            attachAPNMap.put(AUTHENTICATION_TYPE, cellular.getAuthenticationType().toString());
        }

        attachAPNMap.put(USERNAME, cellular.getUsername());
        attachAPNMap.put(PASSWORD, cellular.getPassword());

        List<APNConfiguration> listAPNConfigurations = cellular.getApnConfigurations();
        List<Object> apnList = new ArrayList<Object>();

        if (listAPNConfigurations != null) {
            for (APNConfiguration apnConfiguration : listAPNConfigurations) {

                Map<String, Object> apnMap = new HashMap<String, Object>();
                apnMap.put(ATTACH_APN_NAME, apnConfiguration.getConfigurationName());

                if(apnConfiguration.getAuthenticationType() != null) {
                    apnMap.put(AUTHENTICATION_TYPE, apnConfiguration.getAuthenticationType().toString());
                }

                apnMap.put(USERNAME, apnConfiguration.getUsername());
                apnMap.put(PASSWORD, apnConfiguration.getPassword());
                apnMap.put(PROXY_SERVER, apnConfiguration.getProxyServer());
                apnMap.put(PROXY_PORT, apnConfiguration.getProxyPort());

                apnList.add(apnMap);
            }
        }

        Map<String, Object> commandMap = cellular.getCommandMap();
        commandMap.put(ATTACH_APN, attachAPNMap);

        if (!apnList.isEmpty()) {
            commandMap.put(APN_ARRAY, apnList);
        }

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

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

        return payloadOperationWrapper;
    }

    public PayloadOperationWrapper createAPNPayload(APNConfig apnConfig) throws PListException,
            ProfileConfigurationException {

        PayloadProperties payloadProperties = generateCommonElementsAPN(apnConfig,
                OperationUtils.getTenantNameFromOperationID(), OperationUtils.isPayloadRemoveDisallowedForTenant());

        apnConfig.validateRequest();

        Map<String, Object> defaultsDataMap = new HashMap<String, Object>();
        defaultsDataMap.put(DEFAULT_DOMAIN_NAME, COM_APPLE_MANAGED_CARRIER);

        List<LegacyAPNConfiguration> listAPNConfigurations = apnConfig.getApnConfigurations();
        List<Object> apnList = new ArrayList<Object>();

        if (listAPNConfigurations != null) {
            for (LegacyAPNConfiguration apnConfiguration : listAPNConfigurations) {

                Map<String, Object> apnMap = new HashMap<String, Object>();
                apnMap.put(APN_NAME, apnConfiguration.getApn());
                apnMap.put(APN_USERNAME, apnConfiguration.getUsername());

                if(apnConfiguration.getPassword() != null) {
                    apnMap.put(APN_PASSWORD, apnConfiguration.getPassword().getBytes());
                }

                apnMap.put(APN_PROXY_SERVER, apnConfiguration.getProxyServer());
                apnMap.put(APN_PROXY_PORT, apnConfiguration.getProxyPort());

                apnList.add(apnMap);
            }
        }

        if (!apnList.isEmpty()) {
            defaultsDataMap.put(APN_ARRAY_LEGACY, apnList);
        }

        Map<String, Object> commandMap = apnConfig.getCommandMap();
        commandMap.put(DEFAULTS_DATA, defaultsDataMap);

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

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

        return payloadOperationWrapper;
    }

    private PayloadProperties generateCommonElementsCellular(Cellular cellular, String tenantName,
                                                       boolean payloadRemoveDisallowed) {

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

        cellular.populateCommandPayloadElements(payloadProperties);

        return payloadProperties;
    }

    private PayloadProperties generateCommonElementsAPN(APNConfig apnConfig, String tenantName,
                                                boolean payloadRemoveDisallowed) {

        PayloadProperties payloadProperties = new PayloadProperties();
        payloadProperties.setTenantName(tenantName);
        payloadProperties.setPayloadType(PayloadOperation.PayloadType.APN.getPayloadType());
        payloadProperties.setPayloadIdentifier(apnConfig.getUUID());
        payloadProperties.setPayloadDisplayName(APN_PAYLOAD_DISPLAY_NAME);
        payloadProperties.setPayloadDescription(String.format(APN_PAYLOAD_DESCRIPTION, tenantName));
        payloadProperties.setPayloadRemoveDisallowed(payloadRemoveDisallowed);

        apnConfig.populateCommandPayloadElements(payloadProperties);

        return payloadProperties;
    }
}
