using aeqw89.DataKeys;
using HtmlAgilityPack;
using System.Text.Json.Serialization;
namespace Beam.Dynamic {
public class Binding(DataKey key) : IKeyed {
public Binding(string key) : this(new DataKey(key)) { }
public Binding() : this("") { }
[JsonRequired]
public DataKey Key { get; set; } = key;
[JsonRequired]
public BindingType Type { get; set; }
public string? ArrayDelimiters { get; set; }
public string? XPath { get; set; }
public string? CssPath { get; set; }
public string? Text { get; set; }
private IDataProvider? Provider_;
public IDataProvider? Provider {
get => Provider_;
set {
if (value is null)
return;
if (value is not IDataProvider)
throw new InvalidOperationException();
var constructor = value.GetType().GetConstructor([]);
if (!constructor?.IsPublic ?? true)
throw new InvalidOperationException();
Provider_ = value;
}
}
public HtmlNode? ResolveNode(HtmlDocument doc) {
if (XPath is not null)
return doc.DocumentNode.SelectSingleNode(XPath);
if (CssPath is not null)
return doc.DocumentNode.ThenByClasses(CssPath.Split('/'));
if (Provider is not null)
return Provider.GetNode(doc);
return null;
}
public string ResolveString(HtmlDocument doc) {
if (XPath is not null)
return doc.DocumentNode.SelectSingleNode(XPath)?.InnerText ?? "";
if (CssPath is not null)
return doc.DocumentNode.ThenByClasses(CssPath.Split('/'))?.InnerText ?? "";
if (Provider is not null)
return Provider.Get(doc);
return "";
}
public string[] ResolveArray(HtmlDocument doc) {
if (Type is not BindingType.Array)
return [];
var str = ResolveString(doc);
return str.Split(ArrayDelimiters);
}
public dynamic? Resolve(HtmlDocument doc) => Type switch {
BindingType.Single => ResolveString(doc),
BindingType.Array => ResolveArray(doc),
BindingType.UseProvider => Provider?.Get(doc),
_ => null
};
}
}