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

// ReSharper disable PossibleMultipleEnumeration

namespace RalphsDotNet.Extension
{
    public static class EnumerableExtensions
    {
        /// <summary>
        ///     Run an action parallel on each entry in a list
        /// </summary>
        /// <returns>
        ///     The same list for run a query or whatever
        /// </returns>
        /// <param name='list'>
        ///     the enumerable which contains the parameter for the action
        /// </param>
        /// <param name='action'>
        ///     the action to run
        /// </param>
        /// <typeparam name='T'>
        ///     type of the parameter for the action
        /// </typeparam>
        public static void ParallelAction<T>(this IEnumerable<T> list, Action<T> action)
        {
            Parallel.ForEach(list, action);
        }

        /// <summary>
        ///     Run an action serial on each entry in a list
        /// </summary>
        /// <returns>
        ///     The same list for run a query or whatever
        /// </returns>
        /// <param name='list'>
        ///     the enumerable which contains the parameter for the action
        /// </param>
        /// <param name='action'>
        ///     the action to run
        /// </param>
        /// <typeparam name='T'>
        ///     type of the parameter for the action
        /// </typeparam>
        public static void SerialAction<T>(this IEnumerable<T> list, Action<T> action)
        {
            foreach (T entry in list)
                action(entry);
        }

        /// <summary>
        ///     Run an action on each entry in a list
        /// </summary>
        /// <returns>
        ///     The same list for run a query or whatever
        /// </returns>
        /// <param name='list'>
        ///     the enumerable which contains the parameter for the action
        /// </param>
        /// <param name='action'>
        ///     the action to run
        /// </param>
        /// <param name='runParallel'>
        ///     should this action run parallel or serial
        /// </param>
        /// <typeparam name='T'>
        ///     type of the parameter for the action
        /// </typeparam>
        public static void Action<T>(this IEnumerable<T> list, Action<T> action, bool runParallel)
        {
            if (runParallel)
                list.ParallelAction(action);
            else
                list.SerialAction(action);
        }

        public static double Average(this IEnumerable<byte> list)
        {
            double cnt = 0;

            list.SerialAction(n => cnt += n);

            return cnt/list.Count();
        }

        public static double Average(this IEnumerable<short> list)
        {
            double cnt = 0;

            list.SerialAction(n => cnt += n);

            return cnt/list.Count();
        }

        public static double Average(this IEnumerable<ushort> list)
        {
            double cnt = 0;

            list.SerialAction(n => cnt += n);

            return cnt/list.Count();
        }

        public static double Average(this IEnumerable<int> list)
        {
            double cnt = 0;

            list.SerialAction(n => cnt += n);

            return cnt/list.Count();
        }

        public static double Average(this IEnumerable<uint> list)
        {
            double cnt = 0;

            list.SerialAction(n => cnt += n);

            return cnt/list.Count();
        }

        public static double Average(this IEnumerable<long> list)
        {
            double cnt = 0;

            list.SerialAction(n => cnt += n);

            return cnt/list.Count();
        }

        public static double Average(this IEnumerable<ulong> list)
        {
            double cnt = 0;

            list.SerialAction(n => cnt += n);

            return cnt/list.Count();
        }
    }
}

// ReSharper restore PossibleMultipleEnumeration