using System.Linq.Expressions;
using System.Text.Json;
using AIStudio.Settings.DataModel;
namespace AIStudio.Settings;
///
/// Represents configuration metadata for a specific class and property.
///
/// The class type that contains the configuration property.
/// The type of the configuration property value.
public record ConfigMeta : ConfigMetaBase
{
public ConfigMeta(Expression> configSelection, Expression> propertyExpression) : base(SettingsManager.ToSettingName(propertyExpression))
{
this.ConfigSelection = configSelection;
this.PropertyExpression = propertyExpression;
}
///
/// The expression to select the configuration class from the settings data.
///
private Expression> ConfigSelection { get; }
///
/// The expression to select the property within the configuration class.
///
private Expression> PropertyExpression { get; }
///
/// The default value for the configuration property. This is used when resetting the property to its default state.
///
public required TValue Default { get; init; }
///
/// The additive value contributions, one per contributing configuration plugin.
///
///
/// Every configuration plugin keeps its own contribution, so removing one of them leaves the
/// contributions of the others intact. Callers that need the overall contribution combine the
/// values themselves: only they know how to combine the concrete type.
///
public IReadOnlyDictionary PluginContributions => this.pluginContributions;
///
public override IReadOnlyCollection ContributingConfigPluginIds => this.pluginContributions.Keys;
private readonly Dictionary pluginContributions = [];
///
/// Stores the additive contribution of one configuration plugin, replacing its previous one.
///
/// The contributed value.
/// The contributing configuration plugin.
public void SetPluginContribution(TValue value, Guid pluginId) => this.pluginContributions[pluginId] = value;
///
public override bool RemovePluginContribution(Guid configPluginId) => this.pluginContributions.Remove(configPluginId);
///
public override string SerializeCurrentValue() => ManagedConfiguration.SerializeManagedScalarValue(this.GetValue());
///
protected override string SerializeCurrentValueAsJson() => JsonSerializer.Serialize(this.GetValue(), SettingsManager.JSON_OPTIONS);
///
protected override bool TrySetValueFromJson(string json)
{
try
{
var value = JsonSerializer.Deserialize(json, SettingsManager.JSON_OPTIONS);
if (value is null)
return false;
this.SetValue(value);
return true;
}
catch (Exception e)
{
Log.LogWarning(e, $"Was not able to restore the value of the setting '{this.SettingName}' from its snapshot '{json}'. Using the default value instead.");
return false;
}
}
///
protected override void Reset()
{
var configInstance = this.ConfigSelection.Compile().Invoke(SettingsManagerAccess.ConfigurationData);
var memberExpression = this.PropertyExpression.GetMemberExpression();
if (memberExpression.Member is System.Reflection.PropertyInfo propertyInfo)
propertyInfo.SetValue(configInstance, this.Default);
}
///
/// Sets the value of the configuration property to the specified value.
///
/// The value to set for the configuration property.
public void SetValue(TValue value)
{
var configInstance = this.ConfigSelection.Compile().Invoke(SettingsManagerAccess.ConfigurationData);
var memberExpression = this.PropertyExpression.GetMemberExpression();
if (memberExpression.Member is System.Reflection.PropertyInfo propertyInfo)
propertyInfo.SetValue(configInstance, value);
}
///
/// Gets the current value of the configuration property.
///
public TValue GetValue()
{
var configInstance = this.ConfigSelection.Compile().Invoke(SettingsManagerAccess.ConfigurationData);
var memberExpression = this.PropertyExpression.GetMemberExpression();
if (memberExpression.Member is System.Reflection.PropertyInfo propertyInfo && propertyInfo.GetValue(configInstance) is TValue value)
return value;
return default!;
}
}