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

import org.wso2.carbon.device.mgt.ios.payload.beans.AppLock;
import org.wso2.carbon.device.mgt.ios.payload.beans.AppStoreApplication;
import org.wso2.carbon.device.mgt.ios.payload.beans.ApplicationOptions;
import org.wso2.carbon.device.mgt.ios.payload.beans.ApplicationUserEnabledOptions;
import org.wso2.carbon.device.mgt.ios.payload.beans.EnterpriseApplication;
import org.wso2.carbon.device.mgt.ios.payload.beans.PayloadOperation;
import org.wso2.carbon.device.mgt.ios.payload.beans.RemoveApplication;
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.plist.PListGenerator;
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 ApplicationOperations {

    private static final String INSTALL_APPLICATION = "InstallApplication";
    private static final String REMOVE_APPLICATION = "RemoveApplication";
    private static final String APPLICATION_IDENTIFIER = "Identifier";
    private static final String MANIFEST_URL = "ManifestURL";
    private static final String STORE_ID = "iTunesStoreID";
    private static final String MANAGEMENT_FLAGS = "ManagementFlags";
    private static final String APP_LOCK_PAYLOAD_DISPLAY_NAME = "App Lock Configurations";
    private static final String APP_LOCK_PAYLOAD_DESCRIPTION = "Air Lock Configurations for %s";
    private static final String DISABLE_TOUCH = "DisableTouch";
    private static final String DISABLE_DEVICE_ROTATION = "DisableDeviceRotation";
    private static final String DISABLE_VOLUME_BUTTONS = "DisableVolumeButtons";
    private static final String DISABLE_RINGER_SWITCH = "DisableRingerSwitch";
    private static final String DISABLE_SLEEP_WAKE_BUTTON = "DisableSleepWakeButton";
    private static final String DISABLE_AUTO_LOCK = "DisableAutoLock";
    private static final String ENABLE_VOICE_OVER = "EnableVoiceOver";
    private static final String ENABLE_ZOOM = "EnableZoom";
    private static final String ENABLE_INVERT_COLORS = "EnableInvertColors";
    private static final String ENABLE_ASSISTIVE_TOUCH = "EnableAssistiveTouch";
    private static final String ENABLE_SPEAK_SELECTION = "EnableSpeakSelection";
    private static final String ENABLE_MONO_AUDIO = "EnableMonoAudio";
    private static final String VOICE_OVER = "VoiceOver";
    private static final String ZOOM = "Zoom";
    private static final String INVERT_COLORS = "InvertColors";
    private static final String ASSISTIVE_TOUCH = "AssistiveTouch";
    private static final String IDENTIFIER = "Identifier";
    private static final String OPTIONS = "Options";
    private static final String USER_ENABLED_OPTIONS = "UserEnabledOptions";
    private static final String APP = "App";

    public String createEnterpriseApplicationPayload(EnterpriseApplication enterpriseApplication)
            throws PListException, ProfileConfigurationException {

        enterpriseApplication.validateRequest();

        Map<String, Object> commandMap = new HashMap<String, Object>();
        commandMap.put(OperationPayloadConstants.REQUEST_TYPE, INSTALL_APPLICATION);
        commandMap.put(MANIFEST_URL, enterpriseApplication.getManifestURL());
        commandMap.put(MANAGEMENT_FLAGS, OperationUtils.mapManagementFlagsForApplications(
                enterpriseApplication.getRemoveAppUponMDMProfileRemoval(),
                enterpriseApplication.getPreventBackupOfAppData()));

        Map<String, Object> payloadMap = new HashMap<String, Object>();
        payloadMap.put(OperationPayloadConstants.COMMAND, commandMap);
        payloadMap.put(OperationPayloadConstants.COMMAND_UUID, enterpriseApplication.getUUID());

        return new PListGenerator().generatePayload(payloadMap);
    }

    public String createAppStoreApplicationPayload(AppStoreApplication appStoreApplication)
            throws PListException, ProfileConfigurationException {

        appStoreApplication.validateRequest();

        Map<String, Object> commandMap = new HashMap<String, Object>();
        commandMap.put(OperationPayloadConstants.REQUEST_TYPE, INSTALL_APPLICATION);
        commandMap.put(STORE_ID, appStoreApplication.getiTunesStoreID());
        commandMap.put(MANAGEMENT_FLAGS, OperationUtils.mapManagementFlagsForApplications(
                appStoreApplication.getRemoveAppUponMDMProfileRemoval(),
                appStoreApplication.getPreventBackupOfAppData()));

        Map<String, Object> payloadMap = new HashMap<String, Object>();
        payloadMap.put(OperationPayloadConstants.COMMAND, commandMap);
        payloadMap.put(OperationPayloadConstants.COMMAND_UUID, appStoreApplication.getUUID());

        return new PListGenerator().generatePayload(payloadMap);
    }

    public String createRemoveApplicationPayload(RemoveApplication removeApplication)
            throws PListException, ProfileConfigurationException {

        removeApplication.validateRequest();

        Map<String, Object> commandMap = new HashMap<String, Object>();
        commandMap.put(OperationPayloadConstants.REQUEST_TYPE, REMOVE_APPLICATION);
        commandMap.put(APPLICATION_IDENTIFIER, removeApplication.getBundleId());

        Map<String, Object> payloadMap = new HashMap<String, Object>();
        payloadMap.put(OperationPayloadConstants.COMMAND, commandMap);
        payloadMap.put(OperationPayloadConstants.COMMAND_UUID, removeApplication.getUUID());

        return new PListGenerator().generatePayload(payloadMap);
    }

    public PayloadOperationWrapper createAppLockPayload(AppLock appLock) throws PListException,
            ProfileConfigurationException {

        PayloadProperties payloadProperties = generateAppLockCommonElements(appLock,
                OperationUtils.getTenantNameFromOperationID(), OperationUtils.isPayloadRemoveDisallowedForTenant());

        appLock.validateRequest();

        Map<String, Object> appLockCommandMap = appLock.getCommandMap();

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

        if (appLock.getAppLockApplication().getOptions() != null) {
            Map<String, Object> optionsMap = new HashMap<String, Object>();
            ApplicationOptions applicationOptions = appLock.getAppLockApplication().getOptions();

            optionsMap.put(DISABLE_TOUCH, applicationOptions.getDisableTouch());
            optionsMap.put(DISABLE_DEVICE_ROTATION, applicationOptions.getDisableDeviceRotation());
            optionsMap.put(DISABLE_VOLUME_BUTTONS, applicationOptions.getDisableVolumeButtons());
            optionsMap.put(DISABLE_RINGER_SWITCH, applicationOptions.getDisableRingerSwitch());
            optionsMap.put(DISABLE_SLEEP_WAKE_BUTTON, applicationOptions.getDisableSleepWakeButton());
            optionsMap.put(DISABLE_AUTO_LOCK, applicationOptions.getDisableAutoLock());
            optionsMap.put(ENABLE_VOICE_OVER, applicationOptions.getEnableVoiceOver());
            optionsMap.put(ENABLE_ZOOM, applicationOptions.getEnableZoom());
            optionsMap.put(ENABLE_INVERT_COLORS, applicationOptions.getEnableInvertColors());
            optionsMap.put(ENABLE_ASSISTIVE_TOUCH, applicationOptions.getEnableAssistiveTouch());
            optionsMap.put(ENABLE_SPEAK_SELECTION, applicationOptions.getEnableSpeakSelection());
            optionsMap.put(ENABLE_MONO_AUDIO, applicationOptions.getEnableMonoAudio());

            applicationMap.put(OPTIONS, optionsMap);
        }

        if (appLock.getAppLockApplication().getUserEnabledOptions() != null) {
            Map<String, Object> userEnabledOptions = new HashMap<String, Object>();
            ApplicationUserEnabledOptions applicationUserEnabledOptions = appLock.getAppLockApplication().
                    getUserEnabledOptions();

            userEnabledOptions.put(VOICE_OVER, applicationUserEnabledOptions.getVoiceOver());
            userEnabledOptions.put(ZOOM, applicationUserEnabledOptions.getZoom());
            userEnabledOptions.put(INVERT_COLORS, applicationUserEnabledOptions.getInvertColors());
            userEnabledOptions.put(ASSISTIVE_TOUCH, applicationUserEnabledOptions.getAssistiveTouch());

            applicationMap.put(USER_ENABLED_OPTIONS, userEnabledOptions);
        }

        applicationMap.put(IDENTIFIER, appLock.getAppLockApplication().getIdentifier());
        appLockCommandMap.put(APP, applicationMap);

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

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

        return payloadOperationWrapper;
    }

    private PayloadProperties generateAppLockCommonElements(AppLock appLock, String tenantName,
                                                            boolean payloadRemoveDisallowed) {

        PayloadProperties payloadProperties = new PayloadProperties();
        payloadProperties.setTenantName(tenantName);
        payloadProperties.setPayloadType(PayloadOperation.PayloadType.APP_LOCK.getPayloadType());
        payloadProperties.setPayloadIdentifier(appLock.getUUID());
        payloadProperties.setPayloadDisplayName(APP_LOCK_PAYLOAD_DISPLAY_NAME);
        payloadProperties.setPayloadDescription(String.format(APP_LOCK_PAYLOAD_DESCRIPTION, tenantName));
        payloadProperties.setPayloadRemoveDisallowed(payloadRemoveDisallowed);

        appLock.populateCommandPayloadElements(payloadProperties);

        return payloadProperties;
    }

}
