private ClientNotificationWithAcknowledgement CreateMessageReceivedNotification(Message message, ServerNotification serverNotification)
		{
			var notification = new ClientNotificationWithAcknowledgement
			{
				{"type", "MessageReceived"},
				{"senderInternalUserId", message.SenderInternalUserId},
				{"messageId", message.MessageId},
				{"senderMessageId", message.SenderMessageId},
				{"receivedExpired", message.ExpiryTimeStamp.HasValue && message.ExpiryTimeStamp <= DateTime.UtcNow},
				{"messageType", message.MessageType},
				{"messageScope", message.MessageScope},
				{"sentTimestamp", message.SentTimestamp},
				{"contextItems", message.ContextItems},
			};

			notification.AcknowledgementDetail = new ClientNotificationAcknowledgement
			{
				Result = NotificationResult.Delivered,
				ServerNotificationId = serverNotification.NotificationId,
				SentTime = serverNotification.CreatedOn,
				Type = serverNotification.Type
			};

			return notification;
		}
		public async Task HandleSimplePushAsync(ServerNotification notification)
		{
			var message = _serialiser.Deserialise<SimplePushMessage>(notification.Data.ToString());
			var expired = message.ExpiryTimeStamp.HasValue && message.ExpiryTimeStamp <= DateTime.UtcNow;
			await _commonMessagingManager.NotifyMessageReceivedAsync(message, notification);

			if (!expired)
			{
				var messageEvent = new SimplePushMessageReceivedEvent
				{
					NotificationId = notification.NotificationId,
					Message = message
				};

				// See if we have interactive config for this platform.
				if (message.ButtonSets != null)
				{
					messageEvent.PlatformButtonSet = message.ButtonSets
						.SingleOrDefault(b => b.Platform == INTERACTIVE_PLATFORM);

					await ProcessPendingActionsOrSaveMessage(message);
				}

				_donkyCore.PublishLocalEvent(messageEvent, DonkyPushLogic.Module);
			}
		}
        private static Task HandlePollNotificationAsync(ServerNotification notification)
        {
            var poll = notification.Data["customData"].ToObject<Poll>();

            if (DonkyCore.Instance.GetService<IAppState>().IsOpen)
            {
                Device.BeginInvokeOnMainThread(async () =>
                {
                    var selectedOption = await Application.Current.MainPage.DisplayActionSheet(poll.Title, null, null, poll.Options);
                    var result = new ContentNotification()
                        .ForUsers("pollresults")
                        .WithCustomContent("Vote", new
                        {
                            pollId = poll.Id,
                            option = selectedOption
                        });
                    await DonkyCore.Instance.NotificationController.SendContentNotificationsAsync(result);
                });
            }
            else
            {
                // TODO: Persist poll for next time app is opened
            }

            return Task.FromResult(0);
        }
		public async Task NotifyMessageReceivedAsync(Message message, ServerNotification serverNotification)
		{
			var notification = CreateMessageReceivedNotification(message, serverNotification);
			await _notificationManager.QueueClientNotificationAsync(notification);
			if (_appState.IsOpen)
			{
				_notificationManager.SynchroniseAsync().ExecuteInBackground();
			}
		}
		public async Task HandleRichMessageAsync(ServerNotification notification)
		{
			var message = _serialiser.Deserialise<RichMessage>(notification.Data.ToString());
			message.ReceivedTimestamp = DateTime.UtcNow;
			var expired = message.ExpiryTimeStamp.HasValue && message.ExpiryTimeStamp <= DateTime.UtcNow;

			if (!expired)
			{
				var data = new RichMessageData
				{
					Id = message.MessageId,
					Message = message
				};

				await _context.RichMessages.AddOrUpdateAsync(data);
				await _context.SaveChangesAsync();

				_eventBus.PublishAsync(new RichMessageReceivedEvent
				{
					Message = message,
					NotificationId = notification.NotificationId,
					Publisher = DonkyRichLogic.Module
				}).ExecuteInBackground();

				if (!message.SilentNotification)
				{
					// Also publish a more generic event that the push UI modules can understand if installed to render alerts
					_eventBus.PublishAsync(new MessageReceivedEvent
					{
						Message = message,
						AlertText = message.Description,
						NotificationId = notification.NotificationId,
						Publisher = DonkyRichLogic.Module
					}).ExecuteInBackground();
				}
			}

			await _commonMessagingManager.NotifyMessageReceivedAsync(message, notification);
		}
		public async Task HandleUserUpdatedAsync(ServerNotification notification)
		{
			var userDetails = await _registrationContext.GetUser();
			var data = _serialiser.Deserialise<UserUpdatedData>(notification.Data.ToString());
			if (data != null)
			{
				userDetails = userDetails ?? new UserDetails();
				userDetails.AdditionalProperties = data.AdditionalProperties;
				userDetails.AvatarAssetId = data.AvatarAssetId;
				userDetails.CountryCode = data.CountryIsoCode;
				userDetails.DisplayName = data.DisplayName;
				userDetails.EmailAddress = data.EmailAddress;
				userDetails.FirstName = data.FirstName;
				userDetails.IsAnonymous = data.IsAnonymous;
				userDetails.LastName = data.LastName;
				userDetails.MobileNumber = data.PhoneNumber;
				userDetails.SelectedTags = data.SelectedTags.ToArray();
				userDetails.UserId = !String.IsNullOrEmpty(data.NewExternalUserId) ? data.NewExternalUserId : data.ExternalUserId;
				await _registrationContext.SetUser(userDetails);
				PublishRegistrationChanged();
			}
		}
		public Task HandleTransmitDebugLogAsync(ServerNotification notification)
		{
			return GetAndSubmitLogAsync(LogSubmissionReason.ManualRequest);
		}
		public Task HandleSyncMessageDeletedAsync(ServerNotification notification)
		{
			var messageId = Guid.Parse(notification.Data.Value<string>("messageId"));
			return DeleteMessagesInternalAsync(false, messageId);
		}
		public Task HandleSyncMessageReadAsync(ServerNotification notification)
		{
			var messageId = Guid.Parse(notification.Data.Value<string>("messageId"));
			return MarkMessageAsReadInternalAsync(messageId, false);
		}