private void MarkFeedRead(RoutedEventArgs e)
        {
            if (_selectedNode == null)
            {
                return;
            }
            SimpleTreeNodeViewModel tvm = (SimpleTreeNodeViewModel)_selectedNode;

            if (tvm.Node is Model.Feed)
            {
                Model.Feed selectedFeed = (Model.Feed)tvm.Node;
                Data.Feed  df           = new Data.Feed(selectedFeed);
                df.MarkAllRead();
            }
            else if (tvm.Node is Model.Host)
            {
                Model.Host selectedHost = (Model.Host)tvm.Node;
                Data.Host  dh           = new Data.Host(selectedHost);
                dh.MarkAllRead();
            }
            else
            {
                return;
            }

            foreach (Article a in Articles)
            {
                a.Unread = false;
            }
        }
        private void MarkFeedRead(RoutedEventArgs e)
        {
            if (_selectedNode == null)
                return;
            SimpleTreeNodeViewModel tvm = (SimpleTreeNodeViewModel)_selectedNode;
            if (tvm.Node is Model.Feed)
            {
                Model.Feed selectedFeed = (Model.Feed)tvm.Node;
                Data.Feed df = new Data.Feed(selectedFeed);
                df.MarkAllRead();
            }
            else if (tvm.Node is Model.Host)
            {
                Model.Host selectedHost = (Model.Host)tvm.Node;
                Data.Host dh = new Data.Host(selectedHost);
                dh.MarkAllRead();
            }
            else
                return;

            foreach (Article a in Articles)
            {
                a.Unread = false;
            }
        }
        private async void EditFeed(RoutedEventArgs e)
        {
            if (_selectedNode == null)
                return;
            SimpleTreeNodeViewModel tvm = (SimpleTreeNodeViewModel)_selectedNode;
            Model.Feed selectedFeed = null;
            if (tvm.Node is Model.Feed)
            {
                selectedFeed = (Model.Feed)tvm.Node;
            }
            else
            {
                if (tvm.Node is Model.Host)
                {
                    try
                    {
                        Model.Host selectedHost = (Model.Host)tvm.Node;
                        IsBrowserVisible = false;
                        RaisePropertyChanged("IsBrowserVisible");
                        MetroDialogSettings diagSettings = new MetroDialogSettings();
                        diagSettings.DefaultText = selectedHost.Zoom.ToString();
                        var ZoomLevel = await _dialogCoordinator.ShowInputAsync(this, "Set Zoom Level", "Enter the desired zoom level for this host: ", diagSettings);
                        int prevZoom = selectedHost.Zoom;
                        selectedHost.Zoom = Int32.Parse(ZoomLevel.ToString());
                        Data.Host dh = new Data.Host(selectedHost);
                        dh.Save();

                        if (prevZoom != selectedHost.Zoom)
                        {
                            var msg = new SendSetZoomMessage(selectedHost.Zoom);
                            msg.SetImmediately = true;
                            Messenger.Default.Send<SendSetZoomMessage>(msg);
                        }
                    }
                    catch (Exception ex)
                    {
                        await _dialogCoordinator.ShowMessageAsync(this, "Set Zoom Level", "Unable to set zoom: " + ex.Message);
                    }
                    finally
                    {
                        IsBrowserVisible = true;
                        RaisePropertyChanged("IsBrowserVisible");
                    }
                }
                return;
            }


            // Hides browser otherwise dialog gets behind it
            IsBrowserVisible = false;
            RaisePropertyChanged("IsBrowserVisible");
            MetroDialogSettings dialogSettings = new MetroDialogSettings();
            dialogSettings.DefaultText = selectedFeed.Location.ToString();
            var FeedText = await _dialogCoordinator.ShowInputAsync(this, "Edit feed", "Enter the URL of the feed:", dialogSettings);
            if (FeedText != null)
            {
                string errMsg = null;
                try
                {
                    Uri feedUri = new Uri(FeedText);
                    Data.Feed f = new Data.Feed(selectedFeed);
                    f.Location = feedUri;
                    f.UpdateFromUri(true, RetentionDays);
                    f.Save(true);
                    InitializeData(true);
                }
                catch (Exception ex)
                {
                    errMsg = ex.Message;
                }
                if (errMsg != null)
                {
                    await _dialogCoordinator.ShowMessageAsync(this, "Edit Feed", "Unable to edit feed with the supplied URL: " + errMsg);
                }
            }
            IsBrowserVisible = true;
            RaisePropertyChanged("IsBrowserVisible");
        }
        private async Task UpdateSingleHostStateEntry(HostsRepository hostsrepo, HostStatesRepository staterepo, EventRepository eventrepo, Data.Host host)
        {
            _logger.LogTrace($"Checking host {host.Name} ({host.Hostname})");

            var state = staterepo.GetForHost(host.Id)
                        .Last();

            var ping = new Ping();

            try
            {
                var reply = await ping.SendPingAsync(host.Hostname, 2000);

                switch (reply.Status)
                {
                case IPStatus.Success:
                    state.Delay = (int)reply.RoundtripTime;
                    switch (reply.RoundtripTime)
                    {
                    case long n when n < 70:
                        state.Status = HostState.StatusEnum.Online;
                        break;

                    case long n when n < 300:
                        state.Status = HostState.StatusEnum.Warning;
                        break;

                    case long n when n < 2000:
                        state.Status = HostState.StatusEnum.Critical;
                        break;

                    default:
                        state.Status = HostState.StatusEnum.Error;
                        break;
                    }

                    await eventrepo.Enqueue(new HostOnlineEvent { HostId = host.Id });

                    break;

                case IPStatus.TimedOut:
                    state.Status = HostState.StatusEnum.Offline;
                    await eventrepo.Enqueue(new HostOfflineEvent { HostId = host.Id });

                    break;

                default:
                    _logger.LogError($"Unknown IPStatus {reply.Status} while checking {host.Hostname}");
                    state.Status = HostState.StatusEnum.Error;
                    break;
                }
            }
            catch (Exception)
            {
                _logger.LogWarning($"Error while checking {host.Name} ({host.Hostname})");
                state.Status = HostState.StatusEnum.Error;
            }
            finally
            {
                _logger.LogTrace($"Check complete for host {host.Name} ({host.Hostname})");
            }
        }
        private async void EditFeed(RoutedEventArgs e)
        {
            if (_selectedNode == null)
            {
                return;
            }
            SimpleTreeNodeViewModel tvm = (SimpleTreeNodeViewModel)_selectedNode;

            Model.Feed selectedFeed = null;
            if (tvm.Node is Model.Feed)
            {
                selectedFeed = (Model.Feed)tvm.Node;
            }
            else
            {
                if (tvm.Node is Model.Host)
                {
                    try
                    {
                        Model.Host selectedHost = (Model.Host)tvm.Node;
                        IsBrowserVisible = false;
                        RaisePropertyChanged("IsBrowserVisible");
                        MetroDialogSettings diagSettings = new MetroDialogSettings();
                        diagSettings.DefaultText = selectedHost.Zoom.ToString();
                        var ZoomLevel = await _dialogCoordinator.ShowInputAsync(this, "Set Zoom Level", "Enter the desired zoom level for this host: ", diagSettings);

                        int prevZoom = selectedHost.Zoom;
                        selectedHost.Zoom = Int32.Parse(ZoomLevel.ToString());
                        Data.Host dh = new Data.Host(selectedHost);
                        dh.Save();

                        if (prevZoom != selectedHost.Zoom)
                        {
                            var msg = new SendSetZoomMessage(selectedHost.Zoom);
                            msg.SetImmediately = true;
                            Messenger.Default.Send <SendSetZoomMessage>(msg);
                        }
                    }
                    catch (Exception ex)
                    {
                        await _dialogCoordinator.ShowMessageAsync(this, "Set Zoom Level", "Unable to set zoom: " + ex.Message);
                    }
                    finally
                    {
                        IsBrowserVisible = true;
                        RaisePropertyChanged("IsBrowserVisible");
                    }
                }
                return;
            }


            // Hides browser otherwise dialog gets behind it
            IsBrowserVisible = false;
            RaisePropertyChanged("IsBrowserVisible");
            MetroDialogSettings dialogSettings = new MetroDialogSettings();

            dialogSettings.DefaultText = selectedFeed.Location.ToString();
            var FeedText = await _dialogCoordinator.ShowInputAsync(this, "Edit feed", "Enter the URL of the feed:", dialogSettings);

            if (FeedText != null)
            {
                string errMsg = null;
                try
                {
                    Uri       feedUri = new Uri(FeedText);
                    Data.Feed f       = new Data.Feed(selectedFeed);
                    f.Location = feedUri;
                    f.UpdateFromUri(true, RetentionDays);
                    f.Save(true);
                    InitializeData(true);
                }
                catch (Exception ex)
                {
                    errMsg = ex.Message;
                }
                if (errMsg != null)
                {
                    await _dialogCoordinator.ShowMessageAsync(this, "Edit Feed", "Unable to edit feed with the supplied URL: " + errMsg);
                }
            }
            IsBrowserVisible = true;
            RaisePropertyChanged("IsBrowserVisible");
        }