using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Stylet
{
    /// <summary>
    /// Generic version of IValidationArapter. Provided for use with StyletIoC
    /// </summary>
    /// <remarks>
    /// Having a generic version allows you implement it using a generic ModelValidator (ModelValidator{T} : IModelValidator{T})
    /// then write a binding rule like this:
    /// builder.Bind(typeof(IModelValidator{})).ToAllImplementations()
    /// and request a new IModelValidator{MyViewModelType} in your ViewModel's constructor.
    /// </remarks>
    /// <typeparam name="T"></typeparam>
    public interface IModelValidator<in T> : IModelValidator
    {
    }

    /// <summary>
    /// Adapter used by ValidationModelBase to perform validation.
    /// </summary>
    /// <remarks>
    /// This should be specialised to the particular ValidationModelBase instance it's validating
    /// </remarks>
    public interface IModelValidator
    {
        /// <summary>
        /// Called by ValidatingModelBase, which passes in an instance of itself.
        /// This allows the IModelValidator to specialize to validating that particular ValidatingModelBase instance
        /// </summary>
        /// <param name="subject"></param>
        void Initialize(object subject);

        /// <summary>
        /// Validate a single property by name, and return an array of validation errors for that property (or null if validation was successful)
        /// </summary>
        /// <param name="propertyName">Property to validate</param>
        /// <returns>Array of validation errors, or null if validation was successful</returns>
        Task<IEnumerable<string>> ValidatePropertyAsync(string propertyName);

        /// <summary>
        /// Validate all properties, and return the results for all properties
        /// </summary>
        /// <remarks>
        /// If a property validates successfully, you MUST return a null entry for it in the returned dictionary!
        /// </remarks>
        /// <returns>A dictionary of property name => array of validation errors (or null if that property validated successfully)</returns>
        Task<Dictionary<string, IEnumerable<string>>> ValidateAllPropertiesAsync();
    }
}
