package org.wso2.carbon.device.mgt.ios.services.impl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation;
import org.wso2.carbon.device.mgt.ios.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.ios.exception.*;
import org.wso2.carbon.device.mgt.ios.exception.BadRequestException;
import org.wso2.carbon.device.mgt.ios.services.DeviceManagementAdminService;
import org.wso2.carbon.device.mgt.ios.api.utils.beans.wrapper.*;
import org.wso2.carbon.device.mgt.ios.api.utils.util.OperationMapping;
import org.wso2.carbon.device.mgt.ios.apns.exception.APNSException;
import org.wso2.carbon.device.mgt.ios.payload.beans.*;
import org.wso2.carbon.device.mgt.ios.payload.exception.ProfileConfigurationException;
import org.wso2.carbon.device.mgt.ios.util.IOSServiceUtils;

import org.wso2.carbon.device.mgt.ios.core.publisher.*;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;

@Path("/admin/devices")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminService {

    private static final Log log = LogFactory.getLog(DeviceManagementAdminServiceImpl.class);

    @POST
    @Produces({ MediaType.APPLICATION_JSON})
    @Path("/cellular")
    public Response addCellularOperation(CellularBeanWrapper cellularBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Installing cellular payload");
        }

        String msg;
        try {
            Cellular cellular = cellularBeanWrapper.getOperation();
            if (cellular == null) {
                msg = "Cellular data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            cellular.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.CELLULAR.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(cellular.toJSON());
            return IOSServiceUtils.getOperationResponse(cellularBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
         } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/apn")
    public Response addAPNOperation(APNBeanWrapper apnBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Installing APN payload");
        }

        String msg;
        try {
            APNConfig apnConfig = apnBeanWrapper.getOperation();
            if (apnConfig == null) {
                msg = "APN bean is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            apnConfig.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.APN.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(apnConfig.toJSON());
            return IOSServiceUtils.getOperationResponse(apnBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/ldap")
    public Response addLDAPOperation(LDAPBeanWrapper ldapBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Installing LDAP payload");
        }

        String msg;
        try {
            LDAP ldap = ldapBeanWrapper.getOperation();
            if (ldap == null) {
                msg = "LDAP data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            ldap.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.LDAP.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(ldap.toJSON());
            return IOSServiceUtils.getOperationResponse(ldapBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/email")
    public Response addEmailOperation(EmailBeanWrapper emailBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Installing Email payload");
        }

        String msg;
        try {
            Email email = emailBeanWrapper.getOperation();
            if (email == null) {
                msg = "EMail data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            email.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.EMAIL.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(email.toJSON());
            return IOSServiceUtils.getOperationResponse(emailBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/enterprise-application")
    public Response installEnterpriseApplicationOperation(EnterpriseApplicationBeanWrapper enterpriseApplicationBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Install enterprise application");
        }

        String msg;
        try {
            EnterpriseApplication enterpriseApplication = enterpriseApplicationBeanWrapper.getOperation();
            if (enterpriseApplication == null) {
                msg = "EnterpriseApplication data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            enterpriseApplication.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.INSTALL_ENTERPRISE_APPLICATION.getCode());
            operation.setType(Operation.Type.COMMAND);
            operation.setPayLoad(enterpriseApplication.toJSON());
            return IOSServiceUtils.getOperationResponse(enterpriseApplicationBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/store-application")
    public Response installStoreApplicationOperation(AppStoreApplicationBeanWrapper appStoreApplicationBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Install app store application");
        }

        String msg;
        try {
            AppStoreApplication appStoreApplication = appStoreApplicationBeanWrapper.getOperation();
            if (appStoreApplication == null) {
                msg = "AppStoreApplication data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            appStoreApplication.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.INSTALL_STORE_APPLICATION.getCode());
            operation.setType(Operation.Type.COMMAND);
            operation.setPayLoad(appStoreApplication.toJSON());
            return IOSServiceUtils.getOperationResponse(appStoreApplicationBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/remove-application")
    public Response removeApplication(RemoveApplicationBeanWrapper removeApplicationBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Removing application");
        }

        String msg;
        try {
            RemoveApplication removeApplication = removeApplicationBeanWrapper.getOperation();
            if (removeApplication == null) {
                msg = "RemoveApplication data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            removeApplication.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.REMOVE_APPLICATION.getCode());
            operation.setType(Operation.Type.COMMAND);
            operation.setPayLoad(removeApplication.toJSON());
            return IOSServiceUtils.getOperationResponse(removeApplicationBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/application-list")
    public Response getApplicationListOperation(List<String> deviceIDs) {

        if (log.isDebugEnabled()) {
            log.debug("Invoking get application list operation");
        }

        String msg;
        try {
            org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation operation =
                    new org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation();
            operation.setCode(OperationMapping.APPLICATION_LIST.getCode());
            operation.setType(Operation.Type.COMMAND);
            return IOSServiceUtils.getOperationResponse(deviceIDs, operation);
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/profile-list")
    public Response getProfileListOperation(List<String> deviceIDs) {

        if (log.isDebugEnabled()) {
            log.debug("Invoking get profile list operation");
        }

        String msg;
        try {
            org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation operation =
                    new org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation();
            operation.setCode(OperationMapping.PROFILE_LIST.getCode());
            operation.setType(Operation.Type.COMMAND);
            return IOSServiceUtils.getOperationResponse(deviceIDs, operation);
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/lock")
    public Response lockDevice(List<String> deviceIDs) {

        if (log.isDebugEnabled()) {
            log.debug("Invoking device lock operation");
        }

        String msg;
        try {
            org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation operation =
                    new org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation();
            operation.setCode(OperationMapping.DEVICE_LOCK.getCode());
            operation.setType(Operation.Type.COMMAND);
            return IOSServiceUtils.getOperationResponse(deviceIDs, operation);
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/enterprise-wipe")
    public Response enterpriseWIPE(List<String> deviceIDs) {

        if (log.isDebugEnabled()) {
            log.debug("Invoking enterprise WIPE operation");
        }

        String msg;
        try {
            org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation operation =
                    new org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation();
            operation.setCode(OperationMapping.ENTERPRISE_WIPE.getCode());
            operation.setType(Operation.Type.COMMAND);
            return IOSServiceUtils.getOperationResponse(deviceIDs, operation);
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/device-info")
    public Response getDeviceInformation(List<String> deviceIDs) {

        if (log.isDebugEnabled()) {
            log.debug("Invoking get device information operation");
        }
        getApplicationListOperation(deviceIDs);
        String msg;
        try {
            org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation operation =
                    new org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation();
            operation.setCode(OperationMapping.DEVICE_INFO.getCode());
            operation.setType(Operation.Type.COMMAND);
            return IOSServiceUtils.getOperationResponse(deviceIDs, operation);
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }


    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/restriction")
    public Response restrictionOperation(RestrictionBeanWrapper restrictionBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding restriction operation");
        }

        String msg;
        try {
            Restriction restriction = restrictionBeanWrapper.getOperation();
            if (restriction == null) {
                msg = "Restriction data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            restriction.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.RESTRICTION.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(restriction.toJSON());
            return IOSServiceUtils.getOperationResponse(restrictionBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/wifi")
    public Response configureWIFI(WIFIBeanWrapper wifiBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding WIFI operation");
        }

        String msg;
        try {
            WIFI wifi = wifiBeanWrapper.getOperation();
            if (wifi == null) {
                msg = "Wifi configuration data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            wifi.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.WIFI.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(wifi.toJSON());
            return IOSServiceUtils.getOperationResponse(wifiBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/ring")
    public Response ringDevice(List<String> deviceIDs) {

        if (log.isDebugEnabled()) {
            log.debug("Adding ring operation");
        }

        String msg;
        try {
            org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation operation =
                    new org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation();
            operation.setCode(OperationMapping.RING.getCode());
            operation.setType(Operation.Type.COMMAND);
            return IOSServiceUtils.getOperationResponse(deviceIDs, operation);
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/location")
    public Response fetchLocation(List<String> deviceIDs) {

        if (log.isDebugEnabled()) {
            log.debug("Adding location operation");
        }

        String msg;
        try {
            org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation operation =
                    new org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation();
            operation.setCode(OperationMapping.DEVICE_LOCATION.getCode());
            operation.setType(Operation.Type.COMMAND);
            return IOSServiceUtils.getOperationResponse(deviceIDs, operation);
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/notification")
    public Response sendNotification(NotificationBeanWrapper notificationBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding message operation");
        }

        String msg;
        try {
            Notification notificationBean = notificationBeanWrapper.getOperation();
            if (notificationBean == null) {
                msg = "Notification data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }

            /** This is not a profile operation. Since you don't have a payload in command operations
             *  had to use this as a profile operation as per the discussion had with the team.
             */
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.NOTIFICATION.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(notificationBean.toJSON());
            return IOSServiceUtils.getOperationResponse(notificationBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/airplay")
    public Response addAirPlayOperation(AirPlayBeanWrapper airPlayBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding AirPlay operation");
        }

        String msg;
        try {
            AirPlay airPlay = airPlayBeanWrapper.getOperation();
            if (airPlay == null) {
                msg = "Airplay configuration data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            airPlay.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.AIR_PLAY.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(airPlay.toJSON());
            return IOSServiceUtils.getOperationResponse(airPlayBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/caldav")
    public Response addCalDAVOperation(CalDAVWrapper calDAVWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding CalDAV operation");
        }

        String msg;
        try {
            CalDAV calDAV = calDAVWrapper.getOperation();
            if (calDAV == null) {
                msg = "CalDAV configuration data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            calDAV.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.CALDAV.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(calDAV.toJSON());
            return IOSServiceUtils.getOperationResponse(calDAVWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/cal-subscription")
    public Response addCalSubscriptionOperation(CalendarSubscriptionWrapper calendarSubscriptionWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding calendar subscription operation");
        }

        String msg;
        try {
            CalendarSubscription calendarSubscription = calendarSubscriptionWrapper.getOperation();
            if (calendarSubscription == null) {
                msg = "Calender-subscription configuration data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            calendarSubscription.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.CALENDAR_SUBSCRIPTION.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(calendarSubscription.toJSON());
            return IOSServiceUtils.getOperationResponse(calendarSubscriptionWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/passcode-policy")
    public Response addPasscodePolicyOperation(PasscodePolicyBeanWrapper passcodePolicyBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding passcode policy operation");
        }

        String msg;
        try {
            PasscodePolicy passcodePolicy = passcodePolicyBeanWrapper.getOperation();
            if (passcodePolicy == null) {
                msg = "Passcode policy configuration data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            passcodePolicy.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.PASSCODE_POLICY.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(passcodePolicy.toJSON());
            return IOSServiceUtils.getOperationResponse(passcodePolicyBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/webclip")
    public Response addWebClipOperation(WebClipBeanWrapper webClipBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding web clip operation");
        }

        String msg;
        try {
            WebClip webClip = webClipBeanWrapper.getOperation();
            if (webClip == null) {
                msg = "Webclip configuration data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            webClip.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.WEB_CLIP.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(webClip.toJSON());
            return IOSServiceUtils.getOperationResponse(webClipBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/vpn")
    public Response addVPNOperation(VPNBeanWrapper vpnBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding VPN operation");
        }

        String msg;
        try {
            VPN vpn = vpnBeanWrapper.getOperation();
            if (vpn == null) {
                msg = "VPN configuration data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            vpn.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.VPN.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(vpn.toJSON());
            return IOSServiceUtils.getOperationResponse(vpnBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/per-app-vpn")
    public Response addPerAppVPNOperation(PerAppVPNBeanWrapper perAppVPNBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding Per App VPN operation");
        }

        String msg;
        try {
            PerAppVPN perAppVPN = perAppVPNBeanWrapper.getOperation();
            if (perAppVPN == null) {
                msg = "PerAppVPN configuration data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            perAppVPN.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.PER_APP_VPN.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(perAppVPN.toJSON());
            return IOSServiceUtils.getOperationResponse(perAppVPNBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/app-to-per-app-vpn-mapping")
    public Response addAppToPerAppVPNMappingOperation(AppToPerAppVPNMappingBeanWrapper appToPerAppVPNMappingBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding app to per app VPN operation");
        }

        String msg;
        try {
            AppToPerAppVPNMapping appToPerAppVPNMapping = appToPerAppVPNMappingBeanWrapper.getOperation();
            if (appToPerAppVPNMapping == null) {
                msg = "AppToPerAPPVPNMapping configuration data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            appToPerAppVPNMapping.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.APP_TO_PER_APP_VPN_MAPPING.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(appToPerAppVPNMapping.toJSON());
            return IOSServiceUtils.getOperationResponse(appToPerAppVPNMappingBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/app-lock")
    public Response addAppLockOperation(AppLockBeanWrapper appLockBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding app lock operation");
        }

        String msg;
        try {
            AppLock appLock = appLockBeanWrapper.getOperation();
            if (appLock == null) {
                msg = "AppLock configuration data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            appLock.validateRequest();
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.APP_LOCK.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(appLock.toJSON());
            return IOSServiceUtils.getOperationResponse(appLockBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/clear-passcode")
    public Response clearPasscode(List<String> deviceIDs) {

        if (log.isDebugEnabled()) {
            log.debug("Invoking get device information operation");
        }
        String msg;
        try {
            org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation operation =
                    new org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation();
            operation.setCode(OperationMapping.CLEAR_PASSCODE.getCode());
            operation.setType(Operation.Type.COMMAND);
            return IOSServiceUtils.getOperationResponse(deviceIDs, operation);
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/remove-profile")
    public Response addRemoveProfileOperation(RemoveProfileBeanWrapper removeProfileBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Adding app lock operation");
        }
        String msg;
        try {
            RemoveProfile removeProfile = removeProfileBeanWrapper.getOperation();
            if (removeProfile == null) {
                msg = "RemoveProfile configuration data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }
            removeProfile.validateRequest();
            /** This is not a profile operation. Since you don't have a payload in command operations
             *  had to use this as a profile operation as per the discussion had with the team.
             */
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.POLICY_REVOKE.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(removeProfile.toJSON());
            return IOSServiceUtils.getOperationResponse(removeProfileBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/installed-restrictions")
    public Response getRestrictions(InstalledRestrictionsBeanWrapper installedRestrictionsBeanWrapper) {

        if (log.isDebugEnabled()) {
            log.debug("Invoking get device information operation");
        }
        String msg;
        try {
            InstalledRestrictions installedRestrictions = installedRestrictionsBeanWrapper.getOperation();

            if (installedRestrictions == null) {
                msg = "InstalledRestriction configuration data is empty";
                throw new BadRequestException(
                        new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
            }

            installedRestrictions.validateRequest();
            /** This is not a profile operation. Since you don't have a payload in command operations
             *  had to use this as a profile operation as per the discussion had with the team.
             */
            ProfileOperation operation = new ProfileOperation();
            operation.setCode(OperationMapping.GET_RESTRICTIONS.getCode());
            operation.setType(Operation.Type.PROFILE);
            operation.setPayLoad(installedRestrictions.toJSON());
            return IOSServiceUtils.getOperationResponse(installedRestrictionsBeanWrapper.getDeviceIDs(), operation);
        } catch (ProfileConfigurationException e) {
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(e.getMessage()).build());
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }

    @POST
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/wipe-data")
    public Response wipeDevice(List<String> deviceIDs) {

        if (log.isDebugEnabled()) {
            StringBuilder builder = new StringBuilder();
            for(String deviceId: deviceIDs) {
                builder.append(deviceId).append(", ");
            }
            log.debug("Invoking device wipe operation for devices [" +  builder.toString() + "]");
        }

        String msg;
        try {
            org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation operation =
                    new org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation();
            operation.setCode(OperationMapping.WIPE_DATA.getCode());
            operation.setType(Operation.Type.COMMAND);
            return IOSServiceUtils.getOperationResponse(deviceIDs, operation);
        } catch (OperationManagementException e) {
            msg = "Issue in retrieving operation management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (DeviceManagementException e) {
            msg = "Issue in retrieving device management service instance";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (APNSException e) {
            msg = "Error occurred when sending push notifications.";
            log.error(msg, e);
            throw new UnexpectedServerErrorException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
        } catch (InvalidDeviceException e) {
            msg = "Invalid Device Identifiers found.";
            log.error(msg, e);
            throw new BadRequestException(
                    new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(msg).build());
        }
    }
}