using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace System
{
    /// <summary>
    /// DateTime扩展
    /// </summary>
    public static partial class DateTimeExtensions
    {
        //public static DateTime ToUUDateTime(this DateTime dateTime)
        //{
        //    return new DateTime(dateTime.Ticks);
        //}
        //public static DateTime ToUUDate(this DateTime dateTime)
        //{
        //    return new DateTime(dateTime.Date.Ticks);
        //}
        public static string ToString_yyyyMMddHHmmssffff(this DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM-dd HH:mm:ss.ffff");
        }
        public static string ToString_yyyyMMddHHmmss(this DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM-dd HH:mm:ss");
        }
        public static string ToString_yyyyMMddHHmm(this DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM-dd HH:mm");
        }
        public static string ToString_yyyyMMddHH(this DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM-dd HH");
        }
        public static string ToString_yyyyMMdd(this DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM-dd");
        }
        public static string To_yyyyMMdd(this DateTime dateTime)
        {
            return dateTime.ToString("yyyyMMdd");
        }
        public static string ToString_yyyyMM(this DateTime dateTime)
        {
            return dateTime.ToString("yyyy-MM");
        }
        public static string ToString_HHmmssffff(this DateTime dateTime)
        {
            return dateTime.ToString("HH:mm:ss.ffff");
        }
        public static string ToString_HHmmss(this DateTime dateTime)
        {
            return dateTime.ToString("HH:mm:ss");
        }
        public static string ToString_HHmm(this DateTime dateTime)
        {
            return dateTime.ToString("HH:mm");
        }
        /// <summary>
        /// 获取两个日期间隔的总月
        /// </summary>
        /// <param name="dateTime"></param>
        /// <param name="other"></param>
        /// <returns></returns>
        public static int MonthDifference(this DateTime dateTime, DateTime other)
        {
            return Math.Abs((dateTime.Year - other.Year - 1) * 12 + (12 - other.Month) + dateTime.Month);
        }


        /// <summary>
        /// 克转换为千克的字符串
        /// </summary>
        /// <param name="gram">克</param>
        /// <param name="separated">千位是否按逗号分开</param>
        /// <returns></returns>
        public static string KGFormat(this int gram, bool separated = false)
        {
            string format = "F3";
            if (separated) format = "N3";
            return (gram / 1000d).ToString(format);
        }

        /// <summary>
        /// 过滤非英文字符或非数字字符
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string FileterNonNumberAndEnChar(this string str)
        {
            if (string.IsNullOrWhiteSpace(str)) return string.Empty;
            return Regex.Replace(str, @"[^a-zA-Z0-9]", "");
        }
    }
    /// <summary>
    /// String类扩展
    /// </summary>
    /// <remarks>
    /// [2013-12-14] Develop by SunLiang.
    /// </remarks>
    public static partial class StringExtensions
    {
        public static bool IsNullOrEmpty(this string s)
        {
            return string.IsNullOrEmpty(s);
        }
        public static string Formater(this string format, params object[] args)
        {
            return string.Format(format, args);
        }
        public static string Formater(this string format, object arg0)
        {
            return string.Format(format, arg0);
        }
        public static string Formater(this string format, string arg0, object arg1)
        {
            return string.Format(format, arg0, arg1);
        }
        public static string Formater(this string format, object arg0, object arg1)
        {
            return string.Format(format, arg0, arg1);
        }
        public static string Formater(this string format, object arg0, object arg1, object arg2)
        {
            return string.Format(format, arg0, arg1, arg2);
        }
        public static string Formater(this string format, IFormatProvider provider, params object[] args)
        {
            return string.Format(provider, format, args);
        }
        public static bool IsMatch(this string s, string pattern)
        {
            if (s == null) return false;
            else return Regex.IsMatch(s, pattern);
        }
        public static string Match(this string s, string pattern)
        {
            if (s == null) return "";
            return Regex.Match(s, pattern).Value;
        }
        public static bool IsInt(this string s)
        {
            int i;
            return int.TryParse(s, out i);
        }
        public static int ToInt(this string s)
        {
            return int.Parse(s);
        }
        /// <summary>
        /// 转Int32位数字类型
        /// </summary>
        /// <param name="s">待转Int数据类型</param>
        /// <param name="defult">转失败则返回默认值,没有输入的默认为0</param>
        /// <returns>转成功后Int数值</returns>
        public static int ToInt(this string s, int defult = 0)
        {
            int value = defult;
            if (int.TryParse(s, out value)) //如果转成int成功则为int
                return value;
            else
                return value;
        }
        public static string ToCamel(this string s)
        {
            if (s.IsNullOrEmpty()) return s;
            return s[0].ToString().ToLower() + s.Substring(1);
        }
        public static string ToPascal(this string s)
        {
            if (s.IsNullOrEmpty()) return s;
            return s[0].ToString().ToUpper() + s.Substring(1);
        }
        /// <summary>
        /// 将字符串表示形式转换为它的等效 32 位有符号整数，如转换失败返回 0
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static int TryConvertInt32(this string s)
        {
            int result = 0;
            int.TryParse(s, out result);
            return result;
        }
        public static bool TryConvertBoolean(this string s)
        {
            bool result = false;
            bool.TryParse(s, out result);
            return result;
        }
        /// <summary>
        /// 将字符串表示形式转换为它的等效Decimal类型，如转换失败返回 0
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static decimal TryConvertDecimal(this string s)
        {
            decimal result = 0;
            decimal.TryParse(s, out result);
            return result;
        }
        /// <summary>
        /// 将字符串表示形式转换为它的等效Double类型，如转换失败返回 0
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static double TryConvertDouble(this string s)
        {
            double result = 0;
            double.TryParse(s, out result);
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static short TryConvertShort(this string s)
        {
            short result = 0;
            short.TryParse(s, out result);
            return result;
        }
        /// <summary>
        /// 将字符串按逗号分割成数组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="s"></param>
        /// <returns></returns>
        public static T[] SplitToArray<T>(this string s) where T : IConvertible
        {
            if (s.IsNullOrEmpty()) return new T[0];
            string[] array = s.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            List<T> ids = new List<T>();
            Type t = typeof(T);
            foreach (var item in array)
            {
                try
                {
                    ids.Add((T)Convert.ChangeType(item, t));
                }
                catch { }
            }
            return ids.ToArray();
        }
        /// <summary>
        /// 将字符串按<see cref="seperator"/>分割成数组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="s"></param>
        /// <param name="seperator">seperator</param>
        /// <returns></returns>
        public static T[] SplitToArray<T>(this string s, params char[] seperator) where T : IConvertible
        {
            if (s.IsNullOrEmpty()) return new T[0];
            string[] array = s.Split(seperator, StringSplitOptions.RemoveEmptyEntries);
            List<T> ids = new List<T>();
            Type t = typeof(T);
            foreach (var item in array)
            {
                ids.Add((T)Convert.ChangeType(item, t));
            }
            return ids.ToArray();
        }
        /// <summary>
        /// 将字符串按<see cref="seperator"/>分割成数组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="s"></param>
        /// <param name="seperator">seperator</param>
        /// <returns></returns>
        public static T[] SplitToArray<T>(this string s, char seperator) where T : IConvertible
        {
            if (s.IsNullOrEmpty()) return new T[0];
            string[] array = s.Split(new[] { seperator }, StringSplitOptions.RemoveEmptyEntries);
            List<T> ids = new List<T>();
            Type t = typeof(T);
            foreach (var item in array)
            {
                ids.Add((T)Convert.ChangeType(item, t));
            }
            return ids.ToArray();
        }
        /// <summary>
        /// 将字符串按逗号分割成数组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="s"></param>
        /// <returns></returns>
        public static List<T> SplitToList<T>(this string s) where T : IConvertible
        {
            if (s.IsNullOrEmpty()) return new List<T>();
            string[] array = s.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            List<T> ids = new List<T>();
            Type t = typeof(T);
            foreach (var item in array)
            {
                ids.Add((T)Convert.ChangeType(item, t));
            }
            return ids;
        }

        public static string TrySubString(this string s, int maxLen)
        {
            if(string.IsNullOrWhiteSpace(s) || s.Length <= maxLen) return s;
            else
            {
                return s.Substring(0, maxLen);
            }
        }

        /// <summary>
        /// 将字符串按<see cref="seperator"/>分割成数组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="s"></param>
        /// <param name="seperator">seperator</param>
        /// <returns></returns>
        public static List<T> SplitToList<T>(this string s, params char[] seperator) where T : IConvertible
        {
            if (s.IsNullOrEmpty()) return new List<T>();
            string[] array = s.Split(seperator, StringSplitOptions.RemoveEmptyEntries);
            List<T> ids = new List<T>();
            Type t = typeof(T);
            foreach (var item in array)
            {
                ids.Add((T)Convert.ChangeType(item, t));
            }
            return ids;
        }
        /// <summary>
        /// 将字符串按<see cref="seperator"/>分割成数组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="s"></param>
        /// <param name="seperator">seperator</param>
        /// <returns></returns>
        public static List<T> SplitToList<T>(this string s, char seperator) where T : IConvertible
        {
            if (s.IsNullOrEmpty()) return new List<T>();
            string[] array = s.Split(new[] { seperator }, StringSplitOptions.RemoveEmptyEntries);
            List<T> ids = new List<T>();
            Type t = typeof(T);
            foreach (var item in array)
            {
                ids.Add((T)Convert.ChangeType(item, t));
            }
            return ids;
        }
         
        //public static  string[] ToArray(string str, int maxLength)
        //{
        //    string[] arr = str.Split(' ', '.');
        //    int page = ((str.Length + maxLength) - 1) / maxLength;
        //    string[] addressArr = new string[page];

        //    int flag = 0;
        //    int t = arr.Count();
        //    for (int i = 0; i < page; i++)
        //    {
        //        string temp = "";
        //        for (int j = 0; j < t; j++)
        //        {
        //            if ((temp += arr[flag] + " ").Length <= maxLength)
        //            {
        //                addressArr[i] += arr[flag] + " ";
        //                flag++;
        //            }
        //        }
        //        t = arr.Count() - flag;
        //    }
        //    return addressArr;
        //}

    }

    /// <summary>
    /// Type 拓展
    /// </summary>
    public static partial class TypeExtensions
    {
        /// <summary>
        /// 确定当前实例是否是继承或者实现某个Type
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsInheritOfType(this Type self, Type type)
        {
            if (type.IsInterface)
                return self.GetInterface(type.Name) != null;
            if (type.IsEnum)
                return self.GetEnumUnderlyingType() == type;
            return self.IsSubclassOf(type);
        }
    }

    public static partial class EnumExtensions
    {
        /// <summary>
        /// 枚举信息
        /// </summary>
        public struct EnumInfo
        {
            /// <summary>
            /// 名称
            /// </summary>
            public string Name { get; set; }
            /// <summary>
            /// 值
            /// </summary>
            public object Value { get; set; }
            /// <summary>
            /// 备注
            /// </summary>
            public string Remark { get; set; }
        }
        //[Obsolete("该方法已经过时，请参考使用 GetName() 或者 GetText() 或者 GetValue() 方法.", false)]
        //public static string AsString(this Enum value)
        //{
        //    FieldInfo fi = value.GetType().GetField(value.ToString());
        //    DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
        //    if ((attributes != null) && (attributes.Length > 0))
        //        return attributes[0].Description;
        //    else
        //        return value.ToString();
        //}
        /// <summary>
        /// 获取枚举值的名称
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetName(this Enum value)
        {
            return Enum.GetName(value.GetType(), value);
        }
        /// <summary>
        ///  获取该枚举的显示值（如果使用了DescriptionAttribute 标签则显示描述中的别名，否则使用 Enum 的名称。）
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetText(this Enum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());
            DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
            if ((attributes != null) && (attributes.Length > 0))
                return attributes[0].Description;
            else
                return value.ToString();
        }
        /// <summary>
        ///  获取该枚举的  Description 标记值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetDescription(this Enum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());
            if (fi == null) return string.Empty;
            DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
            if ((attributes != null) && (attributes.Length > 0))
                return attributes[0].Description;
            else
                return null;
        }

        /// <summary>
        /// 获取枚举代表的值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int GetValue(this Enum value)
        {
            return Convert.ToInt32(value);
        }
        public static T Parse<T>(this Enum enumThis, int value)
        {
            return (T)Enum.Parse(enumThis.GetType(), value.ToString());
        }
        public static T Parse<T>(this Enum enumThis, string value)
        {
            return (T)Enum.Parse(enumThis.GetType(), value);
        }
        /// <summary>
        /// 获取枚举信息(名称,值,备注)
        /// </summary>
        /// <param name="em"></param>
        /// <returns></returns>
        public static List<EnumInfo> GetEnumInfo(Type em)
        {
            List<EnumInfo> emInfos = new List<EnumInfo>();
            var fields = em.GetFields(BindingFlags.Static | BindingFlags.Public);
            foreach (var fi in fields)
            {
                EnumInfo emInfo = new EnumInfo();
                emInfo.Name = fi.Name;
                emInfo.Value = fi.GetRawConstantValue();
                var remarkAttr = fi.GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault();
                if (remarkAttr != null)
                {
                    emInfo.Remark = ((DescriptionAttribute)remarkAttr).Description;
                }
                emInfos.Add(emInfo);
            }
            return emInfos;
        }
        ///// <summary>
        ///// 确定包含Flag标记的枚举是否包含指定值
        ///// </summary>
        //public static bool Has(this Enum source, Enum target)
        //{
        //    var value = Convert.ToInt32(target);
        //    return (Convert.ToInt32(source) & value) == value;
        //}

    }
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public partial class BindComboxEnumType<T>
    {
        public string Name
        {
            get;
            set;
        }

        public string TypeValue
        {
            get;
            set;
        }

        private static readonly List<BindComboxEnumType<T>> bindTypes;

        static BindComboxEnumType()
        {
            bindTypes = new List<BindComboxEnumType<T>>();

            Type t = typeof(T);

            foreach (FieldInfo field in t.GetFields())
            {
                if (field.IsSpecialName == false)
                {
                    BindComboxEnumType<T> bind = new BindComboxEnumType<T>();
                    bind.Name = field.Name;
                    bind.TypeValue = field.GetRawConstantValue().ToString();
                    bindTypes.Add(bind);
                }

            }
        }

        public static List<BindComboxEnumType<T>> BindTypes
        {
            get
            {
                return bindTypes;
            }
        }
    }

    public static partial class ArrayExtensions
    {
        //public static void forEach(this Array array, Action<object> action)
        //{
        //    foreach (var item in array)
        //    {
        //        action(item);
        //    }
        //}
        //public static void forEach<T>(this IEnumerable<T> array, Action<T> action)
        //{
        //    foreach (var item in array)
        //    {
        //        action(item);
        //    }
        //}
    }

    public static partial class StringBuilderExtensions
    {
        public static void TrimStart(this StringBuilder builder, char c)
        {
            TrimStart(builder, new[] { c });
        }
        public static void TrimStart(this StringBuilder builder, params char[] c)
        {
            if (builder.Length == 0) return;
            int a = 0;
            while (c.Contains(builder[a]))
            {
                a++;
            }
            if (a > 0)
            {
                builder = builder.Remove(0, a > builder.Length ? builder.Length : a);
            }
        }
        public static void TrimEnd(this StringBuilder builder, char c)
        {
            TrimEnd(builder, new[] { c });
        }
        public static void TrimEnd(this StringBuilder builder, params char[] c)
        {
            if (builder.Length == 0) return;
            int a = builder.Length;
            while (c.Contains(builder[a]))
            {
                a--;
            }
            if (a < builder.Length)
            {
                builder = builder.Remove(a < 0 ? 0 : a, builder.Length - a);
            }
        }
        public static void Trim(this StringBuilder builder, char c)
        {
            Trim(builder, new[] { c });
        }
        public static void Trim(this StringBuilder builder, params char[] c)
        {
            TrimStart(builder, c);
            TrimEnd(builder, c);
        }
        public static void Concat(this StringBuilder builder, params StringBuilder[] c)
        {
            foreach (var item in c)
            {
                if (!Object.ReferenceEquals(item, c))
                    builder.Append(c.ToString());
            }
        }
    }
    /// <summary>
    /// 将一个实体对象的值复制到另一个对象
    /// </summary>
    public static partial class ObjectExtensions
    {
        public static T Copy<T>(this object obj) where T : class
        {
            if (obj == null) throw new ArgumentNullException("参数不能为null");
            T b = Activator.CreateInstance<T>();
            var properties = b.GetType().GetProperties().Where(p => p.PropertyType.IsPublic && p.CanWrite).ToList();
            var t = obj.GetType().GetProperties();
            foreach (var item in t)
            {
                var pro = properties.FirstOrDefault(x => x.Name == item.Name && x.PropertyType == item.PropertyType);
                if (pro != null)
                {
                    pro.SetValue(b, item.GetValue(obj, null), null);
                }
            }
            return b;
        }

       
    }


    /// <summary>
    /// 将一个集合对象的值复制到另一个对象
    /// </summary>
    public static partial class IListExtensions
    {
        public static IList<T> CopyList<T>(this IEnumerable obj) where T : class
        {
            if (obj == null) throw new ArgumentNullException("参数不能为null");
            Type tp = obj.GetType();
            if (!tp.IsGenericType) throw new ArgumentException("参数类型必须为泛型集合");
            ICollection collection = obj as ICollection;
            IList<T> list = new List<T>();
            foreach (var item in obj)
            {
                list.Add(item.Copy<T>());
            }
            return list;
        }
    }

    public static partial class IntExtensions
    {
        private const string X36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        public static string ConvertTo36(this int val)
        {
            string result = "";
            while (val >= 36)
            {
                result = X36[val % 36] + result;
                val /= 36;
            }
            if (val >= 0) result = X36[val] + result;
            return result;
        }
        public static bool In(this int val, IEnumerable<int> list)
        {
            if (!list.Contains(val))
            {
                return false;
            }
            return true;
        }

        public static string IntArrayFormat(this string src)
        {
            if (!string.IsNullOrWhiteSpace(src))
            {
                var arr = src.Split(",，".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                List<string> ids = new List<string>();
                foreach (string i in arr)
                {
                    if (int.TryParse(i, out int rs))
                        ids.Add(i);
                }
                src = string.Join(",", ids.ToArray());
                return src;
            }
            else return null;
        }

        public static bool IsASCII(this string str)
        {
            return str.All(c => c < 128);
        }

    }
}
