public static CatalogFolderModel ToFolder(this CatalogContentDto catalogContentDto, string authorityUrl, CatalogType type, int catalogId)
        {
            var folderModel = new CatalogFolderModel();
            var folderItems = new List<CatalogItemModel>();

            if (catalogContentDto.Links != null)
            {
                // pagination, next page
                var nextPageLink = catalogContentDto.Links.SingleOrDefault(l => !string.IsNullOrEmpty(l.Rel) && l.Rel.Equals("next")
                                                                            && !string.IsNullOrEmpty(l.Type) &&
                                                                            (l.Type.Contains(CATALOG_LINK_TYPE_PREFIX) || (l.Type.Contains(CATALOG_LINK_TYPE))));
                if (nextPageLink != null)
                {
                    folderModel.NextPageUrl = GetValidUrl(nextPageLink.Href, authorityUrl);
                }
            }

            if (catalogContentDto.Entries != null)
            {
                foreach (var entryDto in catalogContentDto.Entries)
                {
                    CatalogItemModel model = null;

                    // book or just folder
                    var links = entryDto.Links.Where(e =>
                        {
                            if (string.IsNullOrEmpty(e.Rel) || (!e.Rel.StartsWith(REL_ACQUISITION_PREFIX)))
                            {
                                if (string.IsNullOrEmpty(e.Type) 
                                    || !(e.Type.StartsWith(APPLICATION_PREFIX) && FormatConstants.Any(fc => e.Type.Contains(fc)) && !ApparentlyIgnoredFormatConstants.Any(fc => e.Type.Contains(fc))))
                                {
                                    return false;
                                }
                                return true;
                            }

                            return !string.IsNullOrEmpty(e.Type); // && FormatConstants.Any(formatConstant => e.Type.Contains(formatConstant));
                        });

                    if (links.Count() != 0)
                    {
                        // links with price
                        var priceLink = links.SingleOrDefault(l => REL_ACQUISITION_BUY_PREFIX.Equals(l.Rel) && !string.IsNullOrEmpty(l.Href)
                                                                   && l.Prices != null && l.Prices.Any(p => !p.Price.Equals("0.00")));
                        
                        // download links for diff. formats
                        var downloadLinks = (from linkDto in links
                                             where !string.IsNullOrEmpty(linkDto.Type) && !string.IsNullOrEmpty(linkDto.Href) && !REL_ACQUISITION_BUY_PREFIX.Equals(linkDto.Rel)
                                             select new BookDownloadLinkModel
                                                 {
                                                     Type = linkDto.Type, Url = GetValidUrl(linkDto.Href, authorityUrl, true)
                                                 }).Where(dl => FormatConstants.Any(fc => dl.Type.Contains(fc))).ToList();

                        // if there are now supported formats in downloadLinks, but there were some acquisition links with another formats => skip this book.
                        if (!downloadLinks.Any() && priceLink == null)
                        {
                            var htmlBuyLink = links.SingleOrDefault(l => REL_ACQUISITION_BUY_PREFIX.Equals(l.Rel));
                            if (htmlBuyLink == null)
                            {
                                continue;
                            }
                            model = new CatalogItemModel {HtmlUrl = GetValidUrl(htmlBuyLink.Href, authorityUrl)};
                        }
                        else
                        {
                            // this is book
                            BookAcquisitionLinkModel acquisitionLink = null;
                            if (priceLink != null && priceLink.Prices.Any(p => !p.Price.Equals("0.00")))
                            {
                                acquisitionLink = new BookAcquisitionLinkModel
                                {
                                    Type = !string.IsNullOrEmpty(priceLink.DcFormat) ? priceLink.DcFormat : priceLink.Type,
                                    Prices = priceLink.Prices != null ? priceLink.Prices.Select(p => new BookPriceModel { CurrencyCode = p.CurrencyCode, Price = p.Price })
                                                                                        .ToList() : null,
                                    Url = GetValidUrl(priceLink.Href, authorityUrl)
                                };
                            }

                            var id = string.IsNullOrEmpty(entryDto.Id) ? string.Concat(catalogId, "-", entryDto.Title) : entryDto.Id;

                            model = new CatalogBookItemModel
                            {
                                AcquisitionLink = acquisitionLink,
                                Links = downloadLinks,
                                Id = id,
                                TrialLink = type == CatalogType.Litres ? CreateTrialLink(entryDto.Id) : null
                            };
                        }
                    }
                    // check for Litres bookshelf
                    else if (entryDto.Links.Any(l => LITRES_REL_BOOKSHELF_PREFIX.Equals(l.Rel)))
                    {
                        model = new LitresBookshelfCatalogItemModel();
                    }
                    // check for Litres topup
                    else if (entryDto.Links.Any(l => LITRES_REL_TOPUP_PREFIX.Equals(l.Rel)))
                    {
                        model = new LitresTopupCatalogItemModel
                            {
                                HtmlUrl = LITRES_PUT_MONEY_LINK_FORMAT,
                                Title = LITRES_REL_TOPUP_TITLE
                            };
                    }
                    else
                    {
                        // this is default folder
                        if (model == null)
                        {
                            model = new CatalogItemModel();
                        }
                    }

                    // title
                    if (string.IsNullOrEmpty(model.Title))
                    {
                        if (entryDto.Title == null)
                        {
                            continue;
                        }
                        if (!string.IsNullOrEmpty(entryDto.Title.Text))
                        {
                            model.Title = entryDto.Title.Text;
                        }
                        else if (!string.IsNullOrEmpty(entryDto.Title.DivValue))
                        {
                            model.Title = entryDto.Title.DivValue;
                        }
                        else
                        {
                            continue;
                        }
                    }

                    // description
                    model.Description = entryDto.Content != null && !string.IsNullOrEmpty(entryDto.Content.Value)
                                            ? entryDto.Content.Value
                                            : string.Empty;

                    // author
                    model.Author = entryDto.Author != null && !string.IsNullOrEmpty(entryDto.Author.Name)
                                        ? entryDto.Author.Name
                                        : string.Empty;

                    // opds catalog url
                    if (!(model is LitresTopupCatalogItemModel) && string.IsNullOrEmpty(model.HtmlUrl))
                    {
                        var catalogLink = entryDto.Links.FirstOrDefault(l => !string.IsNullOrEmpty(l.Type) && (l.Type.Contains(CATALOG_LINK_TYPE_PREFIX) || l.Type.Contains(CATALOG_LINK_TYPE) || l.Type.Contains(LITRES_CATALOG_LINK_TYPE_)));
                        if (catalogLink != null)
                        {
                            model.OpdsUrl = GetValidUrl(catalogLink.Href, authorityUrl);
                        }
                    }

                    // html url, to open in browser
                    var htmlLink = entryDto.Links.FirstOrDefault(l => HTML_TEXT_LINK_TYPE.Equals(l.Type) && !string.IsNullOrEmpty(l.Href));
                    if (htmlLink != null)
                    {
                        if (string.IsNullOrEmpty(model.HtmlUrl))
                        {
                            model.HtmlUrl = GetValidUrl(htmlLink.Href, authorityUrl);
                        }
                    }

                    //image
                    var imageLinks = entryDto.Links.Where(l => !string.IsNullOrEmpty(l.Type) && l.Type.Equals(IMAGE_LINK_TYPE));
                    if (imageLinks.Any())
                    {
                        if (imageLinks.Count() > 1)
                        {
                            var imageLink = imageLinks.SingleOrDefault(l => l.Rel.Equals(REL_IMAGE_PREFIX));
                            if (imageLink != null)
                            {
                                model.ImageUrl = new Uri(GetValidUrl(imageLink.Href, authorityUrl, true));
                            }
                        }
                        else
                        {
                            model.ImageUrl = new Uri(GetValidUrl(imageLinks.First().Href, authorityUrl, true));
                        }
                    }

                    // decoding of description & title
                    model.Description = HttpUtility.HtmlDecode(model.Description);
                    model.Title = HttpUtility.HtmlDecode(model.Title);
                    model.Author = HttpUtility.HtmlDecode(model.Author);

                    if (model.Description.Contains("<") && model.Description.Contains(">"))
                    {
                        model.Description = HtmlToText.Convert(model.Description);
                    }
                    model.Description = model.Description.Trim();
                    if (model.Author.Contains("<") && model.Author.Contains(">"))
                    {
                        model.Author = HtmlToText.Convert(model.Author);
                    }

                    folderItems.Add(model);
                }
            }

            folderModel.Items = folderItems;
            return folderModel;
        }
        public static CatalogFolderModel ToFolder(this CatalogContentDto catalogContentDto, string authorityUrl, CatalogType type, int catalogId)
        {
            var folderModel = new CatalogFolderModel();
            var folderItems = new List <CatalogItemModel>();

            if (catalogContentDto.Links != null)
            {
                // pagination, next page
                var nextPageLink = catalogContentDto.Links.SingleOrDefault(l => !string.IsNullOrEmpty(l.Rel) && l.Rel.Equals("next") &&
                                                                           !string.IsNullOrEmpty(l.Type) &&
                                                                           (l.Type.Contains(CATALOG_LINK_TYPE_PREFIX) || (l.Type.Contains(CATALOG_LINK_TYPE))));
                if (nextPageLink != null)
                {
                    folderModel.NextPageUrl = GetValidUrl(nextPageLink.Href, authorityUrl);
                }
            }

            if (catalogContentDto.Entries != null)
            {
                foreach (var entryDto in catalogContentDto.Entries)
                {
                    CatalogItemModel model = null;

                    // book or just folder
                    var links = entryDto.Links.Where(e =>
                    {
                        if (string.IsNullOrEmpty(e.Rel) || (!e.Rel.StartsWith(REL_ACQUISITION_PREFIX)))
                        {
                            if (string.IsNullOrEmpty(e.Type) ||
                                !(e.Type.StartsWith(APPLICATION_PREFIX) && FormatConstants.Any(fc => e.Type.Contains(fc)) && !ApparentlyIgnoredFormatConstants.Any(fc => e.Type.Contains(fc))))
                            {
                                return(false);
                            }
                            return(true);
                        }

                        return(!string.IsNullOrEmpty(e.Type));    // && FormatConstants.Any(formatConstant => e.Type.Contains(formatConstant));
                    });

                    if (links.Count() != 0)
                    {
                        // links with price
                        var priceLink = links.SingleOrDefault(l => REL_ACQUISITION_BUY_PREFIX.Equals(l.Rel) && !string.IsNullOrEmpty(l.Href) &&
                                                              l.Prices != null && l.Prices.Any(p => !p.Price.Equals("0.00")));

                        // download links for diff. formats
                        var downloadLinks = (from linkDto in links
                                             where !string.IsNullOrEmpty(linkDto.Type) && !string.IsNullOrEmpty(linkDto.Href) && !REL_ACQUISITION_BUY_PREFIX.Equals(linkDto.Rel)
                                             select new BookDownloadLinkModel
                        {
                            Type = linkDto.Type, Url = GetValidUrl(linkDto.Href, authorityUrl, true)
                        }).Where(dl => FormatConstants.Any(fc => dl.Type.Contains(fc))).ToList();

                        // if there are now supported formats in downloadLinks, but there were some acquisition links with another formats => skip this book.
                        if (!downloadLinks.Any() && priceLink == null)
                        {
                            var htmlBuyLink = links.SingleOrDefault(l => REL_ACQUISITION_BUY_PREFIX.Equals(l.Rel));
                            if (htmlBuyLink == null)
                            {
                                continue;
                            }
                            model = new CatalogItemModel {
                                HtmlUrl = GetValidUrl(htmlBuyLink.Href, authorityUrl)
                            };
                        }
                        else
                        {
                            // this is book
                            BookAcquisitionLinkModel acquisitionLink = null;
                            if (priceLink != null && priceLink.Prices.Any(p => !p.Price.Equals("0.00")))
                            {
                                acquisitionLink = new BookAcquisitionLinkModel
                                {
                                    Type   = !string.IsNullOrEmpty(priceLink.DcFormat) ? priceLink.DcFormat : priceLink.Type,
                                    Prices = priceLink.Prices != null?priceLink.Prices.Select(p => new BookPriceModel {
                                        CurrencyCode = p.CurrencyCode, Price = p.Price
                                    })
                                             .ToList() : null,
                                                 Url = GetValidUrl(priceLink.Href, authorityUrl)
                                };
                            }

                            var id = string.IsNullOrEmpty(entryDto.Id) ? string.Concat(catalogId, "-", entryDto.Title) : entryDto.Id;

                            model = new CatalogBookItemModel
                            {
                                AcquisitionLink = acquisitionLink,
                                Links           = downloadLinks,
                                Id        = id,
                                TrialLink = type == CatalogType.Litres ? CreateTrialLink(entryDto.Id) : null
                            };
                        }
                    }
                    // check for Litres bookshelf
                    else if (entryDto.Links.Any(l => LITRES_REL_BOOKSHELF_PREFIX.Equals(l.Rel)))
                    {
                        model = new LitresBookshelfCatalogItemModel();
                    }
                    // check for Litres topup
                    else if (entryDto.Links.Any(l => LITRES_REL_TOPUP_PREFIX.Equals(l.Rel)))
                    {
                        model = new LitresTopupCatalogItemModel
                        {
                            HtmlUrl = LITRES_PUT_MONEY_LINK_FORMAT,
                            Title   = LITRES_REL_TOPUP_TITLE
                        };
                    }
                    else
                    {
                        // this is default folder
                        if (model == null)
                        {
                            model = new CatalogItemModel();
                        }
                    }

                    // title
                    if (string.IsNullOrEmpty(model.Title))
                    {
                        if (entryDto.Title == null)
                        {
                            continue;
                        }
                        if (!string.IsNullOrEmpty(entryDto.Title.Text))
                        {
                            model.Title = entryDto.Title.Text;
                        }
                        else if (!string.IsNullOrEmpty(entryDto.Title.DivValue))
                        {
                            model.Title = entryDto.Title.DivValue;
                        }
                        else
                        {
                            continue;
                        }
                    }

                    // description
                    model.Description = entryDto.Content != null && !string.IsNullOrEmpty(entryDto.Content.Value)
                                            ? entryDto.Content.Value
                                            : string.Empty;

                    // author
                    model.Author = entryDto.Author != null && !string.IsNullOrEmpty(entryDto.Author.Name)
                                        ? entryDto.Author.Name
                                        : string.Empty;

                    // opds catalog url
                    if (!(model is LitresTopupCatalogItemModel) && string.IsNullOrEmpty(model.HtmlUrl))
                    {
                        var catalogLink = entryDto.Links.FirstOrDefault(l => !string.IsNullOrEmpty(l.Type) && (l.Type.Contains(CATALOG_LINK_TYPE_PREFIX) || l.Type.Contains(CATALOG_LINK_TYPE) || l.Type.Contains(LITRES_CATALOG_LINK_TYPE_)));
                        if (catalogLink != null)
                        {
                            model.OpdsUrl = GetValidUrl(catalogLink.Href, authorityUrl);
                        }
                    }

                    // html url, to open in browser
                    var htmlLink = entryDto.Links.FirstOrDefault(l => HTML_TEXT_LINK_TYPE.Equals(l.Type) && !string.IsNullOrEmpty(l.Href));
                    if (htmlLink != null)
                    {
                        if (string.IsNullOrEmpty(model.HtmlUrl))
                        {
                            model.HtmlUrl = GetValidUrl(htmlLink.Href, authorityUrl);
                        }
                    }

                    //image
                    var imageLinks = entryDto.Links.Where(l => !string.IsNullOrEmpty(l.Type) && l.Type.Equals(IMAGE_LINK_TYPE));
                    if (imageLinks.Any())
                    {
                        if (imageLinks.Count() > 1)
                        {
                            var imageLink = imageLinks.SingleOrDefault(l => l.Rel.Equals(REL_IMAGE_PREFIX));
                            if (imageLink != null)
                            {
                                model.ImageUrl = new Uri(GetValidUrl(imageLink.Href, authorityUrl, true));
                            }
                        }
                        else
                        {
                            model.ImageUrl = new Uri(GetValidUrl(imageLinks.First().Href, authorityUrl, true));
                        }
                    }

                    // decoding of description & title
                    model.Description = HttpUtility.HtmlDecode(model.Description);
                    model.Title       = HttpUtility.HtmlDecode(model.Title);
                    model.Author      = HttpUtility.HtmlDecode(model.Author);

                    if (model.Description.Contains("<") && model.Description.Contains(">"))
                    {
                        model.Description = HtmlToText.Convert(model.Description);
                    }
                    model.Description = model.Description.Trim();
                    if (model.Author.Contains("<") && model.Author.Contains(">"))
                    {
                        model.Author = HtmlToText.Convert(model.Author);
                    }

                    folderItems.Add(model);
                }
            }

            folderModel.Items = folderItems;
            return(folderModel);
        }