using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Apewer.Internals
{

    internal class CollectionHelper
    {

        #region 排序。

        public static List<T> Sort<T>(List<T> list, Func<T, T, int> comparison)
        {
            if (list == null) return null;
            if (comparison == null) return list;
            list.Sort(new Comparison<T>(comparison));
            return list;
        }

        public static List<T> Ascend<T>(List<T> list) where T : IComparable<T>
        {
            if (list == null) return null;
            list.Sort((a, b) => a.CompareTo(b));
            return list;
        }

        public static List<T> Descend<T>(List<T> list) where T : IComparable<T>
        {
            if (list == null) return null;
            list.Sort((a, b) => -a.CompareTo(b));
            return list;
        }

        public static Dictionary<TKey, TValue> SortKey<TKey, TValue>(Dictionary<TKey, TValue> dict, Func<TKey, TKey, int> comparison)
        {
            if (dict == null) return null;
            if (comparison == null) return null;
            var list = new List<KeyValuePair<TKey, TValue>>(dict);
            list.Sort(new Comparison<KeyValuePair<TKey, TValue>>((a, b) => comparison(a.Key, b.Key)));
            dict.Clear();
            foreach (var item in list) dict.Add(item.Key, item.Value);
            return dict;
        }

        public static Dictionary<TKey, TValue> SortValue<TKey, TValue>(Dictionary<TKey, TValue> dict, Func<TValue, TValue, int> comparison)
        {
            if (dict == null) return null;
            if (comparison == null) return dict;
            var list = new List<KeyValuePair<TKey, TValue>>(dict);
            list.Sort(new Comparison<KeyValuePair<TKey, TValue>>((a, b) => comparison(a.Value, b.Value)));
            dict.Clear();
            foreach (var item in list) dict.Add(item.Key, item.Value);
            return dict;
        }

        #endregion

        public static T First<T>(IEnumerable<T> collection, T failed = default(T))
        {
            if (collection == null) return failed;

            var array = collection as T[];
            if (array != null) return array.Length > 0 ? array[0] : failed;

            var list = collection as IList<T>;
            if (list != null) return list.Count > 0 ? list[0] : failed;

            foreach (var item in collection) return item;
            return failed;
        }

        public static T Last<T>(IEnumerable<T> collection, T failed = default(T))
        {
            if (collection == null) return failed;

            var array = collection as T[];
            if (array != null) return array.Length > 0 ? array[array.Length - 1] : failed;

            var list = collection as IList<T>;
            if (list != null) return list.Count > 0 ? list[list.Count - 1] : failed;

            var value = failed;
            foreach (var item in collection) value = item;
            return value;
        }

        // 安全转换为 List<T> 对象。可指定排除 NULL 值元素。
        public static List<T> ToList<T>(IEnumerable<T> objects, bool excludeNull = false)
        {
            if (objects == null) return new List<T>();

            var list = new List<T>();
            var collection = objects as ICollection;
            if (collection != null)
            {
                list.AddRange(objects);
            }
            else
            {
                var group = 1024;
                var added = 0;
                var capacity = 0;
                if (objects != null)
                {
                    foreach (var item in objects)
                    {
                        if (excludeNull && item == null) continue;
                        if (added == capacity)
                        {
                            capacity += group;
                            list.Capacity = capacity;
                        }
                        list.Add(item);
                        added += 1;
                    }
                }
                list.Capacity = added;
            }
            return list;
        }

        // 安全转换为 T[] 对象。可指定排除 NULL 值元素。
        public static T[] ToArray<T>(IEnumerable<T> objects, bool excludeNull = false)
        {
            if (objects == null) return new T[0];
            if (objects is T[]) return (T[])objects;

            var collection = objects as ICollection;
            if (collection != null)
            {
                var array = new T[collection.Count];
                collection.CopyTo(array, 0);
                return array;
            }
            else
            {
                var group = 1024;
                var array = new T[group];
                var added = 0;
                var capacity = 0;
                foreach (var item in objects)
                {
                    if (excludeNull && item == null) continue;
                    if (added == capacity)
                    {
                        capacity += group;
                        var temp = new T[capacity];
                        Array.Copy(array, 0, temp, 0, added);
                        array = temp;
                    }
                    array[added] = item;
                    added += 1;
                }
                if (added < 1 || added == capacity) return array;
                var collapsed = new T[added];
                Array.Copy(array, 0, collapsed, 0, added);
                return collapsed;
            }
        }

        public static bool IsEmpty<T>(IEnumerable<T> objects)
        {
            if (objects == null) return true;
            if (objects is T[]) return ((T[])objects).LongLength == 0;
            if (objects is ICollection<T>) return ((ICollection<T>)objects).Count == 0;
            foreach (var i in objects) return false;
            return true;
        }

        public static bool NotEmpty<T>(IEnumerable<T> objects) => !IsEmpty<T>(objects);

        // 判断集合包含特定值。
        public static bool Contains<T>(IEnumerable<T> objects, T cell)
        {
            if (objects == null) return false;

            // objects 实现了含有 Contains 方法的接口。
            if (objects is ICollection<T>) return ((ICollection<T>)objects).Contains(cell);

            // cell 无效。
            if (cell == null)
            {
                foreach (var i in objects)
                {
                    if (i == null) return true;
                }
                return false;
            }

            // cell 有效,进行默认比较。
            var comparer = EqualityComparer<T>.Default;
            foreach (var i in objects)
            {
                if (comparer.Equals(i, cell)) return true;
            }
            return false;
        }

        // 获取集合中元素的数量。
        public static int Count<T>(IEnumerable<T> objects)
        {
            if (objects == null) return 0;

            var array = objects as T[];
            if (array != null) return array.Length;

            var collection = objects as ICollection<T>;
            if (collection != null) return collection.Count;

            var count = 0;
            foreach (var cell in objects) count++;
            return count;
        }

        // 对元素去重,且去除 NULL 值。
        public static T[] Distinct<T>(IEnumerable<T> items)
        {
            if (items == null) throw new ArgumentNullException(nameof(items));
            var count = Count(items);
            var added = 0;
            var array = new T[count];

            var comparer = EqualityComparer<T>.Default;
            foreach (var item in items)
            {
                if (item == null) continue;

                var contains = false;
                foreach (var i in array)
                {
                    if (comparer.Equals(i, item))
                    {
                        contains = true;
                        break;
                    }
                }
                if (contains) continue;

                array[added] = item;
                added++;
            }

            if (added < count)
            {
                var temp = new T[added];
                Array.Copy(array, 0, temp, 0, added);
                array = temp;
            }
            return array;
        }

        // 获取可枚举集合的部分元素。
        public static T[] Slice<T>(IEnumerable<T> objects, int skip = 0, int count = -1, Func<T> stuffer = null)
        {
            if (count == 0) return new T[0];

            var ab = new ArrayBuilder<T>();
            var added = 0;
            if (skip < 0)
            {
                var end = 0 - skip;
                for (var i = 0; i < end; i++)
                {
                    ab.Add(stuffer == null ? default : stuffer());
                    added++;
                    if (count > 0 && added == count) return ab.Export();
                }
            }
            if (objects != null)
            {
                var offset = 0;
                foreach (var item in objects)
                {
                    if (offset < skip)
                    {
                        offset++;
                        continue;
                    }
                    ab.Add(item);
                    added++;
                    offset++;
                    if (count > 0 && added == count) return ab.Export();
                }
            }
            while (added < count)
            {
                ab.Add(stuffer == null ? default : stuffer());
                added++;
            }
            return ab.Export();
        }

        public static IList<T> Add<T>(IList<T> list, IEnumerable<T> items)
        {
            if (list != null && items != null)
            {
                foreach (var item in items) list.Add(item);
            }
            return list;
        }

        public static bool Add<TKey, TValue>(IList<KeyValuePair<TKey, TValue>> list, TKey key, TValue value)
        {
            if (list == null) return false;
            list.Add(new KeyValuePair<TKey, TValue>(key, value));
            return true;
        }

    }

}