using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;

namespace DeviceRepair.Utils
{
    public static class DataExtend
    {
        public static T ToObject<T>(this DataRow row) where T : new()
        {
            T item = new T();
            foreach (PropertyInfo property in typeof(T).GetProperties())
            {
                if (row.Table.Columns.Contains(property.Name))
                {
                    if (DBNull.Value != row[property.Name])
                    {
                        property.SetValue(item, Convert.ChangeType(row[property.Name], property.PropertyType), null);
                    }
                }
            }
            return item;
        }

        public static List<T> ToList<T>(this DataTable dataTable) where T : new()
        {
            var dataList = new List<T>();

            // 获取目标类型的属性
            var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (DataRow row in dataTable.Rows)
            {
                var obj = new T();

                foreach (var property in properties)
                {
                    if (dataTable.Columns.Contains(property.Name))
                    {
                        Type propertyType = property.PropertyType;
                        object value = row[property.Name];
                        if (value != DBNull.Value)
                        {
                            // 当Property是Nullable类型时，需要获取其UnderlyingType
                            property.SetValue(obj, Convert.ChangeType(value, Nullable.GetUnderlyingType(propertyType) ?? propertyType));
                        }
                    }
                }

                dataList.Add(obj);
            }

            return dataList;
        }

        /// <summary>
        /// Convert a List{T} to a DataTable.
        /// </summary>
        public static DataTable ToDataTable<T>(this List<T> items)
        {
            var tb = new DataTable(typeof(T).Name);

            PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (PropertyInfo prop in props)
            {
                Type t = GetCoreType(prop.PropertyType);
                tb.Columns.Add(prop.Name, t);
            }

            foreach (T item in items)
            {
                var values = new object[props.Length];

                for (int i = 0; i < props.Length; i++)
                {
                    values[i] = props[i].GetValue(item, null);
                }

                tb.Rows.Add(values);
            }

            return tb;
        }

        /// <summary>
        /// Determine of specified type is nullable  指定类型的判定为空
        /// </summary>
        public static bool IsNullable(Type t)
        {
            return !t.IsValueType || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
        }

        /// <summary>
        /// Return underlying type if type is Nullable otherwise return the type
        /// 如果类型为空则返回基础类型，否则返回类型
        /// </summary>
        public static Type GetCoreType(Type t)
        {
            if (t != null && IsNullable(t))
            {
                if (!t.IsValueType)
                {
                    return t;
                }
                else
                {
                    return Nullable.GetUnderlyingType(t);
                }
            }
            else
            {
                return t;
            }
        }

        /// <summary>
        /// 解压数据返回DataSet
        /// </summary>
        /// <param name="addDs"></param>
        /// <returns></returns>
        public static DataSet ExactDataSet(this byte[] addDs)
        {
            if (addDs == null || addDs.Length == 0)
            {
                return new DataSet();
            }

            byte[] kao = ExactZip(addDs);
            System.Data.DataSet ds = new System.Data.DataSet();
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            ms.Write(kao, 0, kao.Length);
            ms.Seek(0, System.IO.SeekOrigin.Begin);
            System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader(ms);
            ds.ReadXml(reader, System.Data.XmlReadMode.Auto);
            ms.Close();
            return ds;
        }

        public static byte[] ExactZip(byte[] needExact)
        {
            System.IO.MemoryStream ret = new System.IO.MemoryStream(needExact);
            System.IO.MemoryStream ret1 = new System.IO.MemoryStream();

            ICSharpCode.SharpZipLib.GZip.GZipInputStream zipIn = new ICSharpCode.SharpZipLib.GZip.GZipInputStream(ret);

            byte[] buffer = new byte[2048];
            int size = 2048;
            while (true)
            {
                size = zipIn.Read(buffer, 0, buffer.Length);
                if (size > 0)
                {
                    ret1.Write(buffer, 0, size);
                }
                else
                {
                    break;
                }
            }
            return ret1.ToArray();
        }

    }
}
