using Ethanol.MalwareSonar.Fuzzy;
/// <summary>
/// Represents a membership function where the membership of each element is explicitly defined by a given value.
/// </summary>
/// <typeparam name="T">The type of elements for which the membership values are defined.</typeparam>
/// <remarks>
/// This class implements a membership function using a dictionary where each key is an element
/// and its corresponding value is the degree of membership in the fuzzy set. It allows for direct specification
/// of membership values for each element.
/// </remarks>
public class ValueBasedMembership<T> : IMembershipFunction<T> where T : notnull
{
    // Dictionary to store the membership values of each element.
    private readonly Dictionary<T, double> _values;

    /// <summary>
    /// Initializes a new instance of the ValueBasedMembership class with the specified membership values.
    /// </summary>
    /// <param name="values">A dictionary mapping elements to their membership values.</param>
    /// <exception cref="ArgumentNullException">Thrown when the provided values dictionary is null.</exception>
    public ValueBasedMembership(Dictionary<T, double> values)
    {
        _values = values ?? throw new ArgumentNullException(nameof(values));
    }

    /// <summary>
    /// Retrieves all the elements that have been defined in the membership function.
    /// </summary>
    /// <returns>An enumerable of elements that are part of the fuzzy set.</returns>
    /// <remarks>
    /// This method returns all the keys from the internal dictionary, representing each element
    /// for which a membership value has been explicitly defined.
    /// </remarks>
    public IEnumerable<T> GetMembers()
    {
        return _values.Select(x => x.Key);
    }

    /// <summary>
    /// Retrieves the membership value of a specific element.
    /// </summary>
    /// <param name="x">The element for which to retrieve the membership value.</param>
    /// <returns>
    /// The membership value of the element. If the element is not found in the dictionary,
    /// a membership value of 0 is returned.
    /// </returns>
    /// <remarks>
    /// This method accesses the dictionary to find the membership value of the given element.
    /// If the element is not present in the dictionary, it is assumed to have no membership in the set,
    /// represented by a value of 0.
    /// </remarks>
    public double GetMembership(T x)
    {
        return _values.TryGetValue(x, out var value) ? value : 0;
    }
}
