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

public static class LinqCompl
{
    public static int FindIndex<T>(this IEnumerable<T> ie, T item)
    {
        var i = 0;
        foreach (var e in ie)
            if (e.Equals(item))
                return i;
            else i++;
        return -1;
    }

    public static IEnumerable<int> SelectIndexesWhere<T>(this IEnumerable<T> ie, System.Func<T, bool> condition)
    {
        return ie.Select((e, i) => i).Where(i => condition(ie.ElementAt(i)));
    }

    public static T GetRandom<T>(this IEnumerable<T> ie) where T : class
    {
        return ie.Count() == 0 ? null : ie.RandomItem();
    }
    public static int GetRandom(this IEnumerable<int> ie)
    {
        return ie.Count() == 0 ? -1 : ie.RandomItem();
    }

    private static T RandomItem<T>(this IEnumerable<T> ie)
    {
        return ie.ElementAt(ie.GetRandomIndex());
    }

    private static T GetRandomExcept<T>(this IEnumerable<T> ie, IEnumerable<T> exceptions) where T : class
    {
        return ie.Where(o => !exceptions.Any(e => e.Equals(o))).GetRandom();
    }

    public static int GetRandomIndex<T>(this IEnumerable<T> ie)
    {
        return Random.Range(0, ie.Count());
    }

    public static bool All<T>(this IEnumerable<T> ie, System.Func<T, int, bool> condition)
    {
        var i = 0;
        return ie.All(e => condition(e, i++));
    }

    public static bool Any<T>(this IEnumerable<T> ie, System.Func<T, int, bool> condition)
    {
        var i = 0;
        return ie.Any(e => condition(e, i++));
    }

    public static T First<T>(this IEnumerable<T> ie, System.Func<T, int, bool> condition)
    {
        var i = 0;
        return ie.First(e => condition(e, i++));
    }

    public static T Last<T>(this IEnumerable<T> ie, System.Func<T, int, bool> condition)
    {
        var i = ie.Count() - 1;
        return ie.Last(e => condition(e, i--));
    }

    public static IEnumerable<T> Where<T>(this IEnumerable<T> ie, System.Func<T, int, bool> condition)
    {
        var i = 0;
        return ie.Where(e => condition(e, i++));
    }

    public static float Sum<T>(this IEnumerable<T> ie, System.Func<T, int, float> condition)
    {
        var i = 0;
        return ie.Sum(e => condition(e, i++));
    }

    public static IEnumerable<T> ForeachWhere<T>(this IEnumerable<T> ie, System.Func<T, bool> condition, System.Action<T> action)
    {
        foreach (var o in ie)
            if (condition(o))
                action(o);

        return ie;
    }

    public static float GetWithFloatingLength(this float f, int n)
    {
        var power = Mathf.Pow(10, n);
        return Mathf.Round(f * power) / power;
    }

    public static string ToHexRGB(this Color c)
    {
        return string.Format("#{0:X2}{1:X2}{2:X2}", ToByte(c.r), ToByte(c.g), ToByte(c.b));
    }

    private static byte ToByte(float f)
    {
        f = Mathf.Clamp01(f);
        return (byte)(f * 255);
    }
}
