private async void StartLoadingSubreddit()
        {
            try
            {
                var reddit    = new RedditService();
                var subreddit = await reddit.GetSubredditAsync("Terraria");

                _resourceManager = new ResourceManager("Cache");
                _resourceManager.Start();

                _postsLeftToLoad = 20;
                var postEnumerator = subreddit.EnumeratePosts(10000, 25).GetEnumerator();

                int c = 0;

                while (_processPosts)
                {
                    while (_postsLeftToLoad > 0 && postEnumerator.MoveNext() && _processPosts)
                    {
                        var post = postEnumerator.Current;
                        _postsLeftToLoad--;

                        c++;
                        //if (!post.HasThumbnail) continue;

                        var graphic = new PostGraphicsObject(post, GraphicsDevice, _resourceManager);
                        lock (_postGraphics)
                            _postGraphics.Add(graphic);

                        DoObjectLayout();
                    }
                    Thread.Sleep(10);
                }

                Console.WriteLine("Posts iterated: " + c);
            }
            catch (Exception exc)
            {
                Console.WriteLine("Loading subreddit failed: " + exc);
            }
        }
        protected override void Update(GameTime time)
        {
            Input.Update(time);

            if (Input.IsKeyPressed(Keys.Escape))
            {
                if (OpenPost != null)
                {
                    OpenPost        = null;
                    _fullPostOffset = Vector2.Zero;
                }
                else
                {
                    Exit();
                }
            }

            Viewport view = GraphicsDevice.Viewport;

            UpdateScroll(view, time);

            if (OpenPost == null)
            {
                UpdateObjectVisibility(view, out _firstVisibleGraphic, out _lastVisibleGraphic);

                if (_firstVisibleGraphic != -1 && _lastVisibleGraphic != -1)
                {
                    RenderObjectGraphics(view, _firstVisibleGraphic, _lastVisibleGraphic);
                    ProcessMouse(_firstVisibleGraphic, _lastVisibleGraphic);
                    LoadThumbnails(_firstVisibleGraphic, _lastVisibleGraphic, 6);

                    if (_postsLeftToLoad == 0 && _lastVisibleGraphic + 15 > _postGraphics.Count)
                    {
                        _postsLeftToLoad += 5;
                    }
                }
            }

            base.Update(time);
        }
        private void ProcessMouse(int firstVisible, int lastVisible)
        {
            var mousePos = Vector2.Transform(Input.MousePosition.ToVector2(), Matrix.Invert(_graphicsMatrix));

            HoveredPost = null;

            for (int i = firstVisible; i < lastVisible + 1; i++)
            {
                var graphic = _postGraphics[i];
                if (graphic.Boundaries.Contains(mousePos))
                {
                    if (Input.IsMousePressed(MouseButton.Left))
                    {
                        OpenPost = graphic;
                    }
                    else
                    {
                        HoveredPost = graphic;
                    }
                    break;
                }
            }
        }
        private void DrawFullPost(GameTime time, Viewport view, PostGraphicsObject post)
        {
            var   builder        = StringBuilderPool.Rent(post.Data.Title.Length + 5);
            float maxCharsInLine = Math.Max(1, GetMaxCharsInView(_font40, view.Width * 1.1f));

            PostGraphicsObject.DivideTextIntoLines(post.Data.Title, builder, (int)maxCharsInLine);

            _spriteBatch.Begin(samplerState: SamplerState.LinearClamp);
            _spriteBatch.DrawString(_font40, builder, new Vector2(8, 4), Color.White);

            if (post.PreviewResponse != null && post.PreviewResponse.ContentLength > 0)
            {
                float p = (float)(post.PreviewResponse.BytesDownloaded / (decimal)post.PreviewResponse.ContentLength);
                if (p >= 0 && p <= 1)
                {
                    var pos = new Vector2(view.Width / 2f, view.Height / 2f);
                    _postLoadingBar.Draw(_spriteBatch, pos, 60, Color.White, 8, p);
                }
            }
            _spriteBatch.End();

            post.UploadPostTexture();
            var postTex = post.PostTexture;

            if (postTex != null)
            {
                SizeF titleSize = _font40.MeasureString(builder);

                float marginX    = 5;
                var   textureDst = new RectangleF(
                    marginX, titleSize.Height + 15, postTex.Width - marginX * 2, postTex.Height);

                float maxWidth = view.Width - marginX * 2;
                float zoom     = maxWidth / textureDst.Width;
                if (zoom < 1f)
                {
                    textureDst.Width  *= zoom;
                    textureDst.Height *= zoom;
                }

                const float scrollUpThreshold   = 0;
                float       scrollDownThreshold = Math.Min(0, -(textureDst.Height + textureDst.Y + 5 - view.Height));

                if (_fullPostOffset.Y > scrollUpThreshold)
                {
                    _fullPostOffset.Y = MathHelper.Lerp(_fullPostOffset.Y, scrollUpThreshold, time.Delta * 30f);
                }
                else if (_fullPostOffset.Y < scrollDownThreshold)
                {
                    _fullPostOffset.Y = MathHelper.Lerp(_fullPostOffset.Y, scrollDownThreshold, time.Delta * 30f);
                }

                _fullPostOffset.Y   += MathHelper.Clamp(_smoothScroll * 10f * time.Delta, -350, 350);
                textureDst.Position += _fullPostOffset;

                _spriteBatch.Begin(samplerState: zoom < 1f ? SamplerState.LinearClamp : SamplerState.PointClamp);
                _spriteBatch.DrawRectangle(textureDst + new RectangleF(-1, -1, 2, 2), Color.BlueViolet, 2f);
                _spriteBatch.Draw(postTex, textureDst, Color.White);
                _spriteBatch.End();
            }

            StringBuilderPool.Return(builder);
        }