using System;
using System.Collections.Generic;
using System.Linq;

namespace Chernobyl.Extensions
{
    /// <summary>
    /// Extensions and utility methods for <see cref="Find{TKey, TValue}"/>.
    /// </summary>
    public static class FindExtensions
    {
        /// <summary>
        /// Returns the <see cref="Find{TKey, TValue}"/> as its <see cref="Action{T1, T2}"/>
        /// equivalent.
        /// </summary>
        /// <typeparam name="TKey">The type of the key.</typeparam>
        /// <typeparam name="TValue">The type of the value to return to the callback.</typeparam>
        /// <param name="find">The method to return as an <see cref="Action{T1, T2}"/>.</param>
        /// <returns><paramref name="find"/> as <see cref="Action{T1, T2}"/>.</returns>
        public static Action<TKey, Action<TValue>> AsAction<TKey, TValue>(this Find<TKey, TValue> find)
        {
            return new Action<TKey, Action<TValue>>(find);
        }

        /// <summary>
        /// Uses the <paramref name="find"/> to locate many values tied to
        /// the <paramref name="keys"/> and returning those values through the 
        /// <paramref name="callback"/> in the order relative to their keys.
        /// </summary>
        /// <param name="find">The method used to locate each item.</param>
        /// <param name="keys">The keys that are tied to the values to locate.</param>
        /// <param name="callback">The method to invoke once all of the values
        /// are located.</param>
        public static void FindMany<TKey, TValue>(this Find<TKey, TValue> find,
                                                  IEnumerable<TKey> keys,
                                                  Callback<IEnumerable<TValue>> callback)
        {
            var callbacks = callback.AsAction().AsMany(keys.Count());
            find.AsAction()
                .Bind(keys)
                .AsOne()
                .Invoke(callbacks);
        }
    }
}