package org.wso2.carbon.device.mgt.ios.util;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementConstants;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceDetailsMgtException;
import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager;
import org.wso2.carbon.device.mgt.ios.api.utils.util.Message;
import org.wso2.carbon.device.mgt.ios.exception.BadRequestException;
import org.wso2.carbon.device.mgt.ios.exception.ResourceNotFoundException;
import org.wso2.carbon.device.mgt.ios.exception.ServiceImplementationException;

import javax.ws.rs.core.MediaType;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class DeviceUtils {

    private static final String DEVICE_ID_NOT_FOUND = "Device Id not found for device found at %s";
    private static final String DEVICE_ID_SERVICE_NOT_FOUND =
            "Issue in retrieving device management service instance for device found at %s";
    private static final String COMMA_SEPARATION_PATTERN = ", ";
    private static final Log log = LogFactory.getLog(DeviceUtils.class);

    public DeviceIdentifier fetchDeviceIdentifierInstance(String deviceId,
                                                          Message message, MediaType responseMediaType) {

        if (deviceId == null || deviceId.trim().isEmpty()) {
            message.setErrorMessage("Empty device id received");
            throw new BadRequestException(message, responseMediaType);
        }

        DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
        deviceIdentifier.setId(deviceId);
        deviceIdentifier.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS);

        try {
            Device device = IOSServiceUtils.getDeviceManagementService().getDevice(deviceIdentifier);

            if (device == null || device.getDeviceIdentifier() == null || device.getDeviceIdentifier().isEmpty()) {
                message.setErrorMessage("Device not found for requested device id");
                throw new ResourceNotFoundException(message, responseMediaType);
            }
        } catch (DeviceManagementException e) {
            message.setErrorMessage("Issue in retrieving device management service instance");
            throw new ServiceImplementationException(message, responseMediaType);
        }

        return deviceIdentifier;
    }

    public static void saveDeviceDetails(DeviceIdentifier deviceIdentifier, String
            deviceInformation) throws DeviceManagementException {

        org.wso2.carbon.device.mgt.common.device.details.DeviceInfo deviceInfo =
                new org.wso2.carbon.device.mgt.common.device.details.DeviceInfo();
        if (deviceInfo.getDeviceDetailsMap() == null) {
            deviceInfo.setDeviceDetailsMap(new HashMap<String, String>());
        }

        JsonParser jsonParser = new JsonParser();
        JsonObject deviceInformationDetails = jsonParser.parse(deviceInformation).getAsJsonObject();

        Set<Map.Entry<String, JsonElement>> entrySet = deviceInformationDetails.entrySet();
        for (Map.Entry<String, JsonElement> entry : entrySet) {
            String key = entry.getKey();
            String value = deviceInformationDetails.get(entry.getKey()).getAsString();
            if (value != null && !value.isEmpty()) {
                switch (key) {
                    case "BatteryLevel":
                        deviceInfo.setBatteryLevel(Double.valueOf(value));
                        deviceInfo.getDeviceDetailsMap().put("batteryLevel", value);
                        break;
                    case "DeviceCapacity":
                        deviceInfo.setInternalTotalMemory(Double.valueOf(value));
                        break;
                    case "AvailableDeviceCapacity":
                        deviceInfo.setInternalAvailableMemory(Double.valueOf(value));
                        break;
                    case "OSVersion":
                        deviceInfo.setOsVersion(value);
                        break;
                    case "ProductName":
                        deviceInfo.setDeviceModel(value);
                        break;
                    default:
                        deviceInfo.getDeviceDetailsMap().put(key, value);
                        break;
                }
            }
        }

        PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
        DeviceInformationManager informationManager = (DeviceInformationManager) ctx
                .getOSGiService(DeviceInformationManager.class, null);
        if (informationManager == null) {
            String msg = "Information Manager service not initialized.";
            log.error(msg);
            throw new IllegalStateException(msg);
        }

        try {
            informationManager.addDeviceInfo(deviceIdentifier, deviceInfo);
        } catch (DeviceDetailsMgtException e) {
            String msg = "Could not store device details of device id: " + deviceIdentifier;
            log.error(msg);
            throw new DeviceManagementException(msg);
        }
    }
}
