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 }; } }