﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KaoriStudio.Core.Helpers
{
	/// <summary>
	/// Helper class for lambdas.
	/// </summary>
	public static class LambdaHelper
	{
#if NETFX_40
		/// <summary>
		/// Creates a <see cref="Func{T, TResult}"/> that performs a specified <see cref="Action"/> and returns a specified value.
		/// </summary>
		/// <typeparam name="I1">The first input type.</typeparam>
		/// <typeparam name="I2">The second input type.</typeparam>
		/// <typeparam name="I3">The third input type.</typeparam>
		/// <typeparam name="I4">The fourth input type.</typeparam>
		/// <typeparam name="I5">The fifth input type.</typeparam>
		/// <typeparam name="I6">The sixth input type.</typeparam>
		/// <typeparam name="I7">The seventh input type.</typeparam>
		/// <typeparam name="I8">The eighth input type.</typeparam>
		/// <typeparam name="O">The output type.</typeparam>
		/// <param name="action">The action to perform.</param>
		/// <param name="returnValue">The value to return.</param>
		/// <returns>A <see cref="Func{T, TResult}"/> that performs <paramref name="action"/> and returns <paramref name="returnValue"/>.</returns>
		public static Func<I1, I2, I3, I4, I5, I6, I7, I8, O> ToFunc<I1, I2, I3, I4, I5, I6, I7, I8, O>(this Action<I1, I2, I3, I4, I5, I6, I7, I8> action,
			O returnValue)
		{
			return (i1, i2, i3, i4, i5, i6, i7, i8) =>
			{
				action(i1, i2, i3, i4, i5, i6, i7, i8);
				return returnValue;
			};
		}

		/// <inheritdoc cref="ToFunc{I1, I2, I3, I4, I5, I6, I7, I8, O}(Action{I1, I2, I3, I4, I5, I6, I7, I8}, O)"/>
		public static Func<I1, I2, I3, I4, I5, I6, I7, O> ToFunc<I1, I2, I3, I4, I5, I6, I7, O>(this Action<I1, I2, I3, I4, I5, I6, I7> action,
			O returnValue)
		{
			return (i1, i2, i3, i4, i5, i6, i7) =>
			{
				action(i1, i2, i3, i4, i5, i6, i7);
				return returnValue;
			};
		}

		/// <inheritdoc cref="ToFunc{I1, I2, I3, I4, I5, I6, I7, I8, O}(Action{I1, I2, I3, I4, I5, I6, I7, I8}, O)"/>
		public static Func<I1, I2, I3, I4, I5, I6, O> ToFunc<I1, I2, I3, I4, I5, I6, O>(this Action<I1, I2, I3, I4, I5, I6> action,
			O returnValue)
		{
			return (i1, i2, i3, i4, i5, i6) =>
			{
				action(i1, i2, i3, i4, i5, i6);
				return returnValue;
			};
		}

		/// <inheritdoc cref="ToFunc{I1, I2, I3, I4, I5, I6, I7, I8, O}(Action{I1, I2, I3, I4, I5, I6, I7, I8}, O)"/>
		public static Func<I1, I2, I3, I4, I5, O> ToFunc<I1, I2, I3, I4, I5, O>(this Action<I1, I2, I3, I4, I5> action,
			O returnValue)
		{
			return (i1, i2, i3, i4, i5) =>
			{
				action(i1, i2, i3, i4, i5);
				return returnValue;
			};
		}
#endif

		/// <inheritdoc cref="ToFunc{I1, I2, I3, I4, I5, I6, I7, I8, O}(Action{I1, I2, I3, I4, I5, I6, I7, I8}, O)"/>
		public static Func<I1, I2, I3, I4, O> ToFunc<I1, I2, I3, I4, O>(this Action<I1, I2, I3, I4> action,
			O returnValue)
		{
			return (i1, i2, i3, i4) =>
			{
				action(i1, i2, i3, i4);
				return returnValue;
			};
		}

		/// <inheritdoc cref="ToFunc{I1, I2, I3, I4, I5, I6, I7, I8, O}(Action{I1, I2, I3, I4, I5, I6, I7, I8}, O)"/>
		public static Func<I1, I2, I3, O> ToFunc<I1, I2, I3, O>(this Action<I1, I2, I3> action,
			O returnValue)
		{
			return (i1, i2, i3) =>
			{
				action(i1, i2, i3);
				return returnValue;
			};
		}

		/// <inheritdoc cref="ToFunc{I1, I2, I3, I4, I5, I6, I7, I8, O}(Action{I1, I2, I3, I4, I5, I6, I7, I8}, O)"/>
		public static Func<I1, I2, O> ToFunc<I1, I2, O>(this Action<I1, I2> action,
			O returnValue)
		{
			return (i1, i2) =>
			{
				action(i1, i2);
				return returnValue;
			};
		}

		/// <inheritdoc cref="ToFunc{I1, I2, I3, I4, I5, I6, I7, I8, O}(Action{I1, I2, I3, I4, I5, I6, I7, I8}, O)"/>
		public static Func<I1, O> ToFunc<I1, O>(this Action<I1> action,
			O returnValue)
		{
			return (i1) =>
			{
				action(i1);
				return returnValue;
			};
		}

		/// <inheritdoc cref="ToFunc{I1, I2, I3, I4, I5, I6, I7, I8, O}(Action{I1, I2, I3, I4, I5, I6, I7, I8}, O)"/>
		public static Func<O> ToFunc<O>(this Action action,
			O returnValue)
		{
			return () =>
			{
				action();
				return returnValue;
			};
		}
	}
}
