/// <summary>
        /// Create a mobile device
        /// </summary>
        /// <param name="deviceMobileObj">DeviceMobileModel</param>
        /// <returns>DeviceDAO</returns>
        public async Task <DeviceDAO> CreateMobileDevice(DeviceMobileModel deviceMobileObj)
        {
            //If device doesn't exist, throw exception
            DeviceDAO deviceEntity = _mapper.Map <DeviceDAO>(deviceMobileObj);

            deviceEntity.Id = null;
            deviceEntity.Id = await _repoDevices.CreateItemAsync(deviceEntity);

            if (_repoDevices.IsDocumentKeyNull(deviceEntity))
            {
                throw new Exception($"An error occured when creating a new device: {deviceMobileObj.DeviceId}");
            }

            return(deviceEntity);
        }
        /// <summary>
        /// Create or update a mobile device
        /// </summary>
        /// <param name="deviceMobile">DeviceMobileModel</param>
        /// <returns>DeviceMobileModel</returns>
        public async Task <DeviceMobileModel> CreateOrUpdateDevice(DeviceMobileModel deviceMobile)
        {
            if (deviceMobile.DeviceId == Guid.Empty && string.IsNullOrEmpty(deviceMobile.MobileId))
            {
                throw new Exception($"Invalid DeviceId and/or MobileId");
            }

            DeviceDAO deviceDAO = null;

            if (deviceMobile.DeviceId != Guid.Empty)
            {
                deviceDAO = await _repoDevices.GetItemAsync(deviceMobile.DeviceId);
            }
            else if (!string.IsNullOrEmpty(deviceMobile.MobileId))
            {
                deviceDAO = await _repoDevices.GetItemAsync(
                    d => (string)d.Custom["MobileId"] == deviceMobile.MobileId);
            }


            if (deviceDAO == null)
            //Create
            {
                deviceDAO = await CreateMobileDevice(deviceMobile);
            }
            else
            //Update
            {
                deviceDAO.Custom = deviceMobile.Custom;
                try
                {
                    await _repoDevices.UpdateItemAsync(deviceDAO);
                }
                catch (DocumentClientException e)
                {
                    //Update concurrency issue, retrying
                    if (e.StatusCode == HttpStatusCode.PreconditionFailed)
                    {
                        return(await CreateOrUpdateDevice(deviceMobile));
                    }
                    throw e;
                }
            }

            return(_mapper.Map <DeviceMobileModel>(deviceDAO));
        }
        public async Task <IActionResult> RegisterDevice([FromBody] DeviceRegistrationModel deviceRegistration)
        {
            try
            {
                RegistrationDescription registerDescription = null;
                DeviceMobileModel       deviceModel         = null;

                switch (deviceRegistration.Platform)
                {
                case "apns":
                    registerDescription = deviceRegistration.Tags != null ?
                                          new AppleRegistrationDescription(deviceRegistration.Identifier, deviceRegistration.Tags) :
                                          new AppleRegistrationDescription(deviceRegistration.Identifier);
                    break;

                case "gcm":
                    registerDescription = deviceRegistration.Tags != null ?
                                          new GcmRegistrationDescription(deviceRegistration.Identifier, deviceRegistration.Tags) :
                                          new GcmRegistrationDescription(deviceRegistration.Identifier);
                    break;

                default:
                    throw new ArgumentException("RegisterDevice: Unsupported platform registration");
                }
                try
                {
                    string newRegistrationId = null;

                    if (deviceRegistration.Identifier != null)
                    {
                        var registrations = await _hubClient.GetRegistrationsByChannelAsync(deviceRegistration.Identifier, 100);

                        foreach (RegistrationDescription registration in registrations)
                        {
                            if (newRegistrationId == null)
                            {
                                newRegistrationId = registration.RegistrationId;
                            }
                            else
                            {
                                await _hubClient.DeleteRegistrationAsync(registration);
                            }
                        }
                    }

                    if (newRegistrationId == null)
                    {
                        newRegistrationId = await _hubClient.CreateRegistrationIdAsync();
                    }
                    registerDescription.RegistrationId = newRegistrationId;
                    RegistrationDescription output = await _hubClient.CreateOrUpdateRegistrationAsync <RegistrationDescription>(registerDescription);

                    if (output != null)
                    {
                        deviceModel = await _devicesDataManager.CreateOrUpdateDevice(
                            new DeviceMobileModel()
                        {
                            DeviceType     = "Mobile",
                            Name           = string.Concat("mobile_", deviceRegistration.Platform, "_", Guid.NewGuid()),
                            Email          = deviceRegistration.UserEmail,
                            MobileId       = deviceRegistration.Identifier,
                            Platform       = deviceRegistration.Platform,
                            RegistrationId = output.RegistrationId
                        });
                    }
                    else
                    {
                        throw new Exception(string.Format("Registration creation or update failed. MobileId: {0}", deviceRegistration.Identifier));
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                return(Ok(deviceModel));
            }
            catch (Exception e)
            {
                return(StatusCode(StatusCodes.Status502BadGateway, e.Message));
            }
        }