/// <summary>
 /// Получить URI страницы борды.
 /// </summary>
 /// <param name="link">Ссылка.</param>
 /// <param name="isReferer">Реферер.</param>
 /// <returns>URI.</returns>
 public Uri GetBoardPageUri(BoardPageLink link, bool isReferer)
 {
     if (!isReferer)
     {
         return new Uri(BaseUri, string.Format("{0}/{1}.json", link.Board, link.Page == 0 ? "index" : link.Page.ToString(CultureInfo.InvariantCulture)));
     }
     if (link.Page == 0)
     {
         return new Uri(BaseUri, string.Format("{0}", link.Board));                
     }
     return new Uri(BaseUri, string.Format("{0}/{1}.html", link.Board, link.Page.ToString(CultureInfo.InvariantCulture)));
 }
 /// <summary>
 /// Парсить данные страницы борды.
 /// </summary>
 /// <param name="data">Данные.</param>
 /// <param name="link">Ссылка.</param>
 /// <returns>Результат.</returns>
 public BoardPageTree ParseBoardPage(BoardEntity2 data, BoardPageLink link)
 {
     var entity = GetEntityTree(data);
     var result = new BoardPageTree()
     {
         Extensions = new List<BoardPageTreeExtension>(),
         LastModified = null,
         Link = link,
         ParentLink = new RootLink()
         {
             Engine = CoreConstants.Engine.Makaba
         },
         PageNumber = link.Page,
         Threads = new List<ThreadPreviewTree>(),
         MaxPage = entity.Pages != null ? entity.Pages.OrderByDescending(p => p).Select(p => (int?)p).FirstOrDefault() : null,
     };
     result.Extensions.Add(new MakabaBoardPageExtension()
     {
         Entity = entity
     });
     if (data.Threads != null)
     {
         foreach (var t in data.Threads)
         {
             var posts = t.Posts.OrderBy(p => p.Number.TryParseWithDefault()).ToArray();
             var tnum = posts.First().Number.TryParseWithDefault();
             var tlink = new ThreadLink()
             {
                 Engine = CoreConstants.Engine.Makaba,
                 Board = link.Board,
                 Thread = tnum,
             };
             var thread = new ThreadPreviewTree()
             {
                 Extensions = new List<PostTreeCollectionExtension>(),
                 Link = tlink,
                 ParentLink = link,
                 ImageCount =
                     t.ImagesCount.TryParseWithDefault() +
                     posts.Sum(p => (p.Files ?? new BoardPostFile2[0]).Length),
                 Omit = t.PostsCount.TryParseWithDefault(),
                 OmitImages = t.ImagesCount.TryParseWithDefault(),
                 ReplyCount = Math.Max(t.PostsCount.TryParseWithDefault() + posts.Count(), 0),
                 Posts = posts.Select(p => Parse(p, tlink, true)).ToList(),
             };
             for (var i = 0; i < thread.Posts.Count; i++)
             {
                 thread.Posts[i].Flags |= PostFlags.ThreadPreview;
                 if (i == 0)
                 {
                     thread.Posts[i].Counter = 1;
                     thread.Posts[i].Flags |= PostFlags.ThreadPreviewOpPost;
                 }
                 else
                 {
                     var ni = thread.Posts.Count - i;
                     thread.Posts[i].Counter = thread.ReplyCount - ni;
                 }
             }
             result.Threads.Add(thread);
         }
     }
     return result;
 }
 /// <summary>
 /// Ссылка JSON.
 /// </summary>
 /// <param name="link">Ссылка.</param>
 /// <returns>Результат.</returns>
 public Uri GetJsonLink(BoardLinkBase link)
 {
     if (link is BoardPageLink)
     {
         return GetBoardPageUri((BoardPageLink)link, false);
     }
     if (link is BoardLink)
     {
         var l = new BoardPageLink()
         {
             Engine = CoreConstants.Engine.Makaba,
             Board = ((BoardLink)link).Board,
             Page = 0,
         };
         return GetBoardPageUri(l, false);
     }
     if (link is ThreadPartLink)
     {
         return GetThreadPartUri(link as ThreadPartLink, false);
     }
     if (link is ThreadLink)
     {
         return GetThreadUri(link as ThreadLink, false);
     }
     if (link is MediaLink)
     {
         return GetMediaLink(link as MediaLink);
     }
     if (link is BoardMediaLink)
     {
         return GetMediaLink(link as BoardMediaLink);
     }
     if (link is YoutubeLink)
     {
         return Services.GetServiceOrThrow<IYoutubeUriService>().GetViewUri((link as YoutubeLink).YoutubeId);
     }
     if (link is BoardCatalogLink)
     {
         return GetCatalogUri(link as BoardCatalogLink, false);
     }
     return null;
 }