using HtmlAgilityPack;
using System.Text.Json.Serialization;
namespace Beam.Dynamic {
public record class DataBindings {
#region ---------------------- Common Bindings ----------------------
[JsonIgnore]
public IDataProvider? Title {
get => Get(nameof(Title));
set => Providers[nameof(Title)] = value;
}
[JsonIgnore]
public IDataProvider? Authors {
get => Get(nameof(Authors));
set => Providers[nameof(Authors)] = value;
}
[JsonIgnore]
public IDataProvider? Description {
get => Get(nameof(Description));
set => Providers[nameof(Description)] = value;
}
[JsonIgnore]
public IDataProvider? Content {
get => Get(nameof(Content));
set => Providers[nameof(Content)] = value;
}
[JsonIgnore]
public IDataProvider? Language {
get => Get(nameof(Language));
set => Providers[nameof(Language)] = value;
}
[JsonIgnore]
public IDataProvider? Tags {
get => Get(nameof(Tags));
set => Providers[nameof(Tags)] = value;
}
[JsonIgnore]
public IDataProvider? Publisher {
get => Get(nameof(Publisher));
set => Providers[nameof(Publisher)] = value;
}
[JsonIgnore]
public IDataProvider? PublicationDate {
get => Get(nameof(PublicationDate));
set => Providers[nameof(PublicationDate)] = value;
}
[JsonIgnore]
public IDataProvider? ISBN {
get => Get(nameof(ISBN));
set => Providers[nameof(ISBN)] = value;
}
[JsonIgnore]
public IDataProvider? PageCount {
get => Get(nameof(PageCount));
set => Providers[nameof(PageCount)] = value;
}
[JsonIgnore]
public IDataProvider? CoverImage {
get => Get(nameof(CoverImage));
set => Providers[nameof(CoverImage)] = value;
}
[JsonIgnore]
public IDataProvider? Series {
get => Get(nameof(Series));
set => Providers[nameof(Series)] = value;
}
[JsonIgnore]
public IDataProvider? Edition {
get => Get(nameof(Edition));
set => Providers[nameof(Edition)] = value;
}
[JsonIgnore]
public IDataProvider? Contributors {
get => Get(nameof(Contributors));
set => Providers[nameof(Contributors)] = value;
}
[JsonIgnore]
public IDataProvider? Subjects {
get => Get(nameof(Subjects));
set => Providers[nameof(Subjects)] = value;
}
[JsonIgnore]
public IDataProvider? Rights {
get => Get(nameof(Rights));
set => Providers[nameof(Rights)] = value;
}
[JsonIgnore]
public IDataProvider? TableOfContents {
get => Get(nameof(TableOfContents));
set => Providers[nameof(TableOfContents)] = value;
}
[JsonIgnore]
public IDataProvider? PagesDropDown {
get => Get(nameof(PagesDropDown));
set => Providers[nameof(PagesDropDown)] = value;
}
[JsonIgnore]
public IDataProvider? NextPageButton {
get => Get(nameof(NextPageButton));
set => Providers[nameof(NextPageButton)] = value;
}
[JsonIgnore]
public IDataProvider? PreviousPageButton {
get => Get(nameof(PreviousPageButton));
set => Providers[nameof(PreviousPageButton)] = value;
}
#endregion
public Dictionary Providers { get; set; } = [];
private IDataProvider? Get(string key) {
if (Providers.TryGetValue(key, out var k) && k is IDataProvider ks)
return ks;
return default;
}
public virtual ResolvedBindings Resolve(HtmlDocument doc) {
// explicit fields already handled below
var mappedKeys = new HashSet {
nameof(Title), nameof(Authors), nameof(Description), nameof(Content),
nameof(Language), nameof(Tags), nameof(Publisher), nameof(PublicationDate),
nameof(ISBN), nameof(PageCount), nameof(CoverImage), nameof(Series),
nameof(Edition), nameof(Contributors), nameof(Subjects), nameof(Rights),
nameof(TableOfContents), nameof(PagesDropDown), nameof(NextPageButton),
nameof(PreviousPageButton)
};
var additional = new Dictionary();
foreach (var (key, provider) in Providers) {
if (!mappedKeys.Contains(key) && provider is not null) {
// dynamic call so any IDataProvider works
additional[key] = ((dynamic)provider).Get(doc);
}
}
return new ResolvedBindings {
Title = Title?.Get(doc),
Authors = Authors?.Get(doc) ?? [],
Description = Description?.Get(doc),
Content = Content?.Get(doc),
Language = Language?.Get(doc),
Tags = Tags?.Get(doc) ?? [],
Publisher = Publisher?.Get(doc),
PublicationDate = PublicationDate?.Get(doc),
ISBN = ISBN?.Get(doc),
PageCount = PageCount?.Get(doc),
CoverImage = CoverImage?.Get(doc),
Series = Series?.Get(doc) ?? [],
Edition = Edition?.Get(doc),
Contributors = Contributors?.Get(doc) ?? [],
Subjects = Subjects?.Get(doc) ?? [],
Rights = Rights?.Get(doc),
TableOfContents = TableOfContents?.Get(doc) ?? [],
PagesDropDown = PagesDropDown?.Get(doc),
NextPageButton = NextPageButton?.Get(doc),
PreviousPageButton = PreviousPageButton?.Get(doc),
Additional = additional
};
}
}
public record class ResolvedBindings {
public string? Title { get; set; }
public string[]? Authors { get; set; }
public string? Description { get; set; }
public string? Content { get; set; }
public string[]? Language { get; set; }
public string[]? Tags { get; set; }
public string? Publisher { get; set; }
public DateTimeOffset? PublicationDate { get; set; }
public string? ISBN { get; set; }
public int? PageCount { get; set; }
public SourceLink? CoverImage { get; set; }
public string[]? Series { get; set; }
public int? Edition { get; set; }
public string[]? Contributors { get; set; }
public string[]? Subjects { get; set; }
public string? Rights { get; set; }
public SourceLink[]? TableOfContents { get; set; }
public SourceLink[]? PagesDropDown { get; set; }
public SourceLink? NextPageButton { get; set; }
public SourceLink? PreviousPageButton { get; set; }
///
/// Values resolved from any providers whose keys aren’t represented
/// by the named properties above.
///
public Dictionary Additional { get; set; } = [];
}
}