public override void WireMessages()
        {
            Messenger.Default.Register<VideoMessage>(this, m =>
            {
                PlaylistItems = null;
                switch (m.PlayerSourceType)
                {
                    case PlayerSourceType.Video:
                        if (m.VideoItem != null)
                        {
                            SelectedItem = m.VideoItem;
                            PlaylistItems = null;
                        }
                        break;
                    case PlayerSourceType.Recording:
                        if (m.VideoItem != null)
                        {
                            RecordingItem = m.VideoItem;
                            PlaylistItems = null;
                        }
                        break;
                    case PlayerSourceType.Programme:
                        if (m.VideoItem != null)
                        {
                            ProgrammeItem = m.VideoItem;
                            PlaylistItems = null;
                        }
                        break;
                    case PlayerSourceType.Playlist:
                        PlaylistItems = m.VideoPlaylists;
                        SelectedItem = m.VideoItem;
                        break;
                }

                PlayerSourceType = m.PlayerSourceType;
                _isResume = m.IsResume;
                _startPositionTicks = m.ResumeTicks ?? 0;
            });

            Messenger.Default.Register<NotificationMessage>(this, async m =>
            {
                if (m.Notification.Equals(Constants.Messages.SetResumeMsg))
                {
                    _isResume = true;
                }

                if (m.Notification.Equals(Constants.Messages.SendVideoTimeToServerMsg))
                {
                    try
                    {
                        var totalTicks = _startPositionTicks + PlayedVideoDuration.Ticks;

                        Log.Info("Sending current runtime [{0}] to the server", totalTicks);

                        var info = new PlaybackStopInfo
                        {
                            ItemId = _itemId,
                            PositionTicks = totalTicks
                        };

                        await _playbackManager.ReportPlaybackStopped(info, _streamInfo, App.ServerInfo.Id, AuthenticationService.Current.LoggedInUserId, false, ApiClient);

                        SetPlaybackTicks(totalTicks);

                        if (_timer != null && _timer.IsEnabled)
                        {
                            _timer.Stop();
                        }

                        Messenger.Default.Send(new NotificationMessage(_itemId, totalTicks, Constants.Messages.RefreshResumeMsg));
                    }
                    catch (HttpException ex)
                    {
                        Utils.HandleHttpException("SendVideoTimeToServer", ex, NavigationService, Log);
                    }

                    if (!PlaylistItems.IsNullOrEmpty())
                    {
                        var index = PlaylistItems.IndexOf(SelectedItem);
                        if (index >= 0 && index < PlaylistItems.Count - 1)
                        {
                            SelectedItem = PlaylistItems[index + 1];
                            await InitiatePlayback(false);
                        }
                    }
                }

                if (m.Notification.Equals(Constants.Messages.VideoStateChangedMsg))
                {
                    try
                    {
                        var totalTicks = _startPositionTicks + PlayedVideoDuration.Ticks;
                        var isPaused = m.Sender != null && (bool)m.Sender;

                        if (_timer != null)
                        {
                            if (isPaused)
                            {
                                if (_timer.IsEnabled)
                                {
                                    _timer.Stop();
                                }
                            }
                            else
                            {
                                if (!_timer.IsEnabled)
                                {
                                    _timer.Start();
                                }
                            }
                        }

                        Log.Info("Sending current runtime [{0}] to the server", totalTicks);

                        var info = new PlaybackProgressInfo
                        {
                            IsMuted = false,
                            ItemId = _itemId,
                            PositionTicks = totalTicks,
                            IsPaused = isPaused
                        };

                        await ApiClient.ReportPlaybackProgressAsync(info);
                        SetPlaybackTicks(totalTicks);
                    }
                    catch (HttpException ex)
                    {
                        Utils.HandleHttpException("VideoStateChanged", ex, NavigationService, Log);
                    }
                }
            });
        }
        /// <summary>
        /// Handles the MediaChanged event of the _mediaPlayer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="MediaChangeEventArgs"/> instance containing the event data.</param>
        async void _mediaPlayer_MediaChanged(object sender, MediaChangeEventArgs e)
        {
            if (e.PreviousMedia != null)
            {
                var info = new PlaybackStopInfo
                {
                    ItemId = e.PreviousMedia.Id,
                    UserId = _apiClient.CurrentUserId,
                    PositionTicks = e.EndingPositionTicks
                };

                try
                {
                    await _apiClient.ReportPlaybackStoppedAsync(info);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error sending playback stopped checking for {0}", ex, e.PreviousMedia.Name);
                }
            }

            if (e.NewMedia != null)
            {
                try
                {
                    var queueTypes = _mediaPlayer.CanQueue
                                ? new List<string> { e.NewMedia.MediaType }
                                : new List<string> { };

                    var info = new PlaybackStartInfo
                    {
                        ItemId = e.NewMedia.Id,
                        UserId = _apiClient.CurrentUserId,
                        IsSeekable = _mediaPlayer.CanSeek,
                        QueueableMediaTypes = queueTypes.ToArray()
                    };

                    await _apiClient.ReportPlaybackStartAsync(info);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error sending playback start checking for {0}", ex, e.NewMedia.Name);
                }
            }
        }
        /// <summary>
        /// Handles the PlaybackCompleted event of the _mediaPlayer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="PlaybackStopEventArgs"/> instance containing the event data.</param>
        async void _mediaPlayer_PlaybackCompleted(object sender, PlaybackStopEventArgs e)
        {
            _mediaPlayer.MediaChanged -= _mediaPlayer_MediaChanged;
            _mediaPlayer.PlaybackCompleted -= _mediaPlayer_PlaybackCompleted;

            if (_timer != null)
            {
                _timer.Dispose();
                _timer = null;
            }

            if (e.EndingMedia != null)
            {
                var info = new PlaybackStopInfo
                {
                    ItemId = e.EndingMedia.Id,
                    UserId = _apiClient.CurrentUserId,
                    PositionTicks = e.EndingPositionTicks
                };

                try
                {
                    await _apiClient.ReportPlaybackStoppedAsync(info);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error sending playback stopped checking for {0}", ex, e.EndingMedia.Name);
                }
            }
        }
        /// <summary>
        /// Handles the MediaChanged event of the _mediaPlayer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="MediaChangeEventArgs"/> instance containing the event data.</param>
        async void _mediaPlayer_MediaChanged(object sender, MediaChangeEventArgs e)
        {
            if (e.PreviousMedia != null)
            {
                var info = new PlaybackStopInfo
                {
                    ItemId = e.PreviousMedia.Id,
                    PositionTicks = e.EndingPositionTicks
                };

                var apiClient = _connectionManager.GetApiClient(e.PreviousMedia);

                try
                {
                    await apiClient.ReportPlaybackStoppedAsync(info);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error sending playback stopped checking for {0}", ex, e.PreviousMedia.Name);
                }
            }

            if (e.NewMedia != null)
            {
                try
                {
                    var queueTypes = _mediaPlayer.CanQueue
                                ? new List<string> { e.NewMedia.MediaType }
                                : new List<string> { };

                    var info = new PlaybackStartInfo
                    {
                        ItemId = e.NewMedia.Id,

                        CanSeek = _mediaPlayer.CanSeek,
                        QueueableMediaTypes = queueTypes.ToList(),

                        // TODO: Remove this hardcoding
                        PlayMethod = PlayMethod.DirectPlay
                    };

                    var apiClient = _connectionManager.GetApiClient(e.NewMedia);

                    await apiClient.ReportPlaybackStartAsync(info);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error sending playback start checking for {0}", ex, e.NewMedia.Name);
                }
            }
        }
        /// <summary>
        /// Handles the PlaybackCompleted event of the _mediaPlayer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="eventArgs">The <see cref="PlaybackStopEventArgs"/> instance containing the event data.</param>
        async void _mediaPlayer_PlaybackCompleted(object sender, PlaybackStopEventArgs eventArgs)
        {
            _mediaPlayer.MediaChanged -= _mediaPlayer_MediaChanged;
            _mediaPlayer.PlaybackCompleted -= _mediaPlayer_PlaybackCompleted;

            var item = eventArgs.EndingMedia;
            if (item != null)
            {
                var apiClient = _connectionManager.GetApiClient(item);

                var stopInfo = new PlaybackStopInfo
                {
                    ItemId = item.Id,
                    PositionTicks = eventArgs.EndingPositionTicks
                };

                // Have to test this for null because external players are currently not supplying this
                // Also some players will play in contexts not currently supported by common playback managers, e.g. direct play of folder rips, and iso-mounted media
                // Remove when implemented
                if (eventArgs.StreamInfo != null)
                {
                    await _apiPlaybackManager.ReportPlaybackStopped(stopInfo, eventArgs.StreamInfo, item.ServerId, apiClient.CurrentUserId, false, apiClient);
                }
                else
                {
                    await apiClient.ReportPlaybackStoppedAsync(stopInfo);
                }
            }

            var timer = _timer;
            if (timer != null)
            {
                timer.Dispose();
                _timer = null;
            }
        }
        /// <summary>
        /// Handles the MediaChanged event of the _mediaPlayer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="eventArgs">The <see cref="MediaChangeEventArgs"/> instance containing the event data.</param>
        async void _mediaPlayer_MediaChanged(object sender, MediaChangeEventArgs eventArgs)
        {
            if (eventArgs.PreviousMedia != null)
            {
                var apiClient = _connectionManager.GetApiClient(eventArgs.PreviousMedia);

                var stopInfo = new PlaybackStopInfo
                {
                    ItemId = eventArgs.PreviousMedia.Id,
                    PositionTicks = eventArgs.EndingPositionTicks
                };

                // Have to test this for null because external players are currently not supplying this
                // Also some players will play in contexts not currently supported by common playback managers, e.g. direct play of folder rips, and iso-mounted media
                // Remove when implemented
                if (eventArgs.PreviousStreamInfo != null)
                {
                    await _apiPlaybackManager.ReportPlaybackStopped(stopInfo, eventArgs.PreviousStreamInfo, eventArgs.PreviousMedia.ServerId, apiClient.CurrentUserId, false, apiClient);
                }
                else
                {
                    await apiClient.ReportPlaybackStoppedAsync(stopInfo);
                }
            }

            if (eventArgs.NewMedia != null)
            {
                try
                {
                    var queueTypes = _mediaPlayer.CanQueue
                                ? new List<string> { eventArgs.NewMedia.MediaType }
                                : new List<string> { };

                    var info = new PlaybackStartInfo
                    {
                        ItemId = eventArgs.NewMedia.Id,

                        CanSeek = _mediaPlayer.CanSeek,
                        QueueableMediaTypes = queueTypes.ToList(),

                        // TODO: Remove this hardcoding
                        PlayMethod = PlayMethod.DirectPlay
                    };

                    var apiClient = _connectionManager.GetApiClient(eventArgs.NewMedia);

                    await apiClient.ReportPlaybackStartAsync(info);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error sending internalPlaybackManager start checking for {0}", ex, eventArgs.NewMedia.Name);
                }
            }
        }
        /// <summary>
        /// Reports playback progress
        /// </summary>
        /// <param name="info">The information.</param>
        /// <param name="streamInfo">The stream information.</param>
        /// <param name="serverId">The server identifier.</param>
        /// <param name="userId">The user identifier.</param>
        /// <param name="isOffline">if set to <c>true</c> [is offline].</param>
        /// <param name="apiClient">The current apiClient. It can be null if offline</param>
        /// <returns>Task.</returns>
        public async Task ReportPlaybackStopped(PlaybackStopInfo info, StreamInfo streamInfo, string serverId, string userId, bool isOffline, IApiClient apiClient)
        {
            if (isOffline)
            {
                var action = new UserAction
                {
                    Date = DateTime.UtcNow,
                    ItemId = info.ItemId,
                    PositionTicks = info.PositionTicks,
                    ServerId = serverId,
                    Type = UserActionType.PlayedItem,
                    UserId = userId
                };

                await _localAssetManager.RecordUserAction(action).ConfigureAwait(false);
                return;
            }

            if (streamInfo != null)
            {
                info.PlaySessionId = streamInfo.PlaySessionId;

                if (streamInfo.MediaSource != null)
                {
                    info.LiveStreamId = streamInfo.MediaSource.LiveStreamId;
                }
            }

            // Put a try/catch here because we need to stop transcoding regardless
            try
            {
                await apiClient.ReportPlaybackStoppedAsync(info).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error in ReportPlaybackStoppedAsync", ex);
            }
        }
        private async Task InformOfStoppedTrack()
        {
            if (_apiClient == null)
            {
                return;
            }

            try
            {
                var track = BackgroundAudioPlayer.Instance.Track;
                if (track != null)
                {
                    var info = new PlaybackStopInfo
                    {
                        ItemId = track.Tag,
                        //UserId = _apiClient.CurrentUserId
                    };
                    await _apiClient.ReportPlaybackStoppedAsync(info);
                }
            }
            catch (HttpException ex)
            {
                _logger.FatalException("InformOfStoppedTrack()", ex);
            }

            NotifyComplete();
        }