using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Reflection;
using System.Data;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Collections;

namespace CK.SCP.Utils
{
    public class ConvertHelper
    {

        /// <summary>
        /// 转换 DataTable 对象为 IList 对象
        /// </summary>
        /// <param name="datas">数据集合</param>
        /// <returns>数组对象</returns>
        public static T[] ToArray<T>(DataTable datas) where T : class, new()
        {
            List<T> list = ToList<T>(datas) as List<T>;
            return list.ToArray();
        }

        /// <summary>
        /// 转换IList对象为DataTable对象
        /// </summary>
        /// <param name="datas">数据集合</param>
        /// <returns>DataTable对象</returns>
        public static DataTable ToDataTable<T>(IList<T> datas)
        {
            return ToDataTable<T>(datas, null);
        }

        /// <summary>
        /// 转换IList对象为DataTable对象
        /// </summary>
        /// <param name="datas">数据集合</param>
        /// <returns>DataTable对象</returns>
        public static DataTable ToDataTable<T>(T[] datas)
        {
            return ToDataTable<T>(datas, null);
        }

        /// <summary>
        /// 转换IList对象为DataTable对象
        /// </summary>
        /// <param name="datas">数据集合</param>
        /// <param name="tableName">要创建的表名</param>
        /// <returns>DataTable对象</returns>
        public static DataTable ToDataTable<T>(IList<T> datas, string tableName)
        {
            Type type = typeof(T);
            if (string.IsNullOrEmpty(tableName))
            {
                tableName = type.Name;
            }
            DataTable table = new DataTable(tableName);
            table.BeginLoadData();
            PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (PropertyInfo info in properties)
            {
                string typeName = info.PropertyType.ToString();
                if (info.PropertyType.IsGenericType)
                {
                    typeName = info.PropertyType.GetGenericArguments()[0].ToString();
                }
                Type type2 = Type.GetType(typeName, false);
                if (type2 != null)
                {
                    table.Columns.Add(info.Name, type2);
                }
            }
            if ((datas != null) && (datas.Count > 0))
            {
                foreach (object obj2 in datas)
                {
                    DataRow row = table.NewRow();
                    foreach (PropertyInfo info2 in properties)
                    {
                        if (info2.PropertyType.IsGenericType )
                        {
                            continue; 
                        }
                        
                        if ((Type.GetType(info2.PropertyType.ToString(), false) != null) && (info2.GetValue(obj2, null) != null))
                        {
                            row[info2.Name] = info2.GetValue(obj2, null);
                        }
                    }
                    table.Rows.Add(row);
                }
            }
            table.EndLoadData();
            table.AcceptChanges();
            return table;
        }

       

        /// <summary>
        /// 转换IList对象为DataTable对象
        /// </summary>
        /// <param name="datas">数据集合</param>
        /// <param name="tableName">要创建的表名</param>
        /// <returns>DataTable对象</returns>
        public static DataTable ToDataTable<T>(T[] datas, string tableName)
        {
            IList<T> list;
            if ((datas == null) || (datas.Length == 0))
            {
                list = new List<T>();
            }
            else
            {
                list = new List<T>(datas);
            }
            return ToDataTable<T>(list, tableName);
        }

        /// <summary>
        /// 转换 DataTable 对象为 IList 对象
        /// </summary>
        /// <param name="datas">数据集合</param>
        /// <returns>IList 对象</returns>
        public static IList<T> ToList<T>(DataTable datas) where T : class, new()
        {
            IList<T> list = new List<T>();
            if ((datas != null) && (datas.Rows.Count != 0))
            {
                PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
                foreach (DataRow row in datas.Rows)
                {
                    T local = Activator.CreateInstance<T>();
                    foreach (DataColumn column in datas.Columns)
                    {
                        object obj2 = null;
                        if (row.RowState == DataRowState.Deleted)
                        {
                            obj2 = row[column, DataRowVersion.Original];
                        }
                        else
                        {
                            obj2 = row[column];
                        }
                        if (obj2 != DBNull.Value)
                        {
                            foreach (PropertyInfo info in properties)
                            {
                                if (column.ColumnName.Equals(info.Name, StringComparison.CurrentCultureIgnoreCase))
                                {
                                    info.SetValue(local, obj2, null);
                                }
                            }
                        }
                    }
                    list.Add(local);
                }
            }
            return list;
        }


            /// <summary>
            /// 转换object为 T 值   
            /// </summary>
            /// <typeparam name="T">T 类型</typeparam>
            /// <param name="obj">要被转换的值</param>
            /// <returns>T 类型值</returns>
            public static T To<T>(object obj)
            {
                return To<T>(obj, default(T));
            }

            /// <summary>
            /// 转换object为 T 值   
            /// </summary>
            /// <typeparam name="T">T 类型</typeparam>
            /// <param name="obj">要被转换的值</param>
            /// <returns>T 类型值</returns>
            public static T To<T>(object obj, T defaultValue)
            {
                if (obj == null)
                {
                    return defaultValue;
                }
                else if (obj is T)
                {
                    return (T)obj;
                }
                else
                {
                    try
                    {
                        Type conversionType = typeof(T);
                        object obj2 = null;
                        if (conversionType.Equals(typeof(Guid)))
                            obj2 = new Guid(Convert.ToString(obj));
                        else
                            obj2 = Convert.ChangeType(obj, conversionType);
                        return (T)obj2;
                    }
                    catch (Exception)
                    {
                        return defaultValue;
                    }
                }
            }

            /// <summary>
            /// 填充客户端提交的值到 T 对象  如appinfo = AppConvert.To<Appinfo>(context.Request.Form);
            /// </summary>
            /// <typeparam name="T">T 类</typeparam>
            /// <param name="datas">客户端提交的值</param>
            /// <returns>T 对象</returns>
            public static T To<T>(NameValueCollection datas) where T : class, new()
            {
                Type type = typeof(T);
                string[] strArray = type.FullName.Split(new char[] { '.' });
                string str = strArray[strArray.Length - 1];
                PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                T local = Activator.CreateInstance<T>();
                foreach (string str2 in datas.AllKeys)
                {
                    string str3 = datas[str2];
                    if (!string.IsNullOrEmpty(str3))
                    {
                        str3 = str3.TrimEnd(new char[0]);
                    }
                    foreach (PropertyInfo info in properties)
                    {
                        string str4 = string.Format("{0}.{1}", str, info.Name);
                        if (str2.Equals(info.Name, StringComparison.CurrentCultureIgnoreCase) || str2.Equals(str4, StringComparison.CurrentCultureIgnoreCase))
                        {
                            string typeName = info.PropertyType.ToString();
                            if (info.PropertyType.IsGenericType)
                            {
                                typeName = info.PropertyType.GetGenericArguments()[0].ToString();
                            }
                            object nullInternal = GetNullInternal(info.PropertyType);
                            Type conversionType = Type.GetType(typeName, false);
                            if (!string.IsNullOrEmpty(str3))
                            {
                                nullInternal = Convert.ChangeType(str3, conversionType);
                            }
                            info.SetValue(local, nullInternal, null);
                        }
                    }
                }
                return local;
            }

            #region 获取类型的默认值
            //另一种获取默认值的方法
            private static object GetDefaultValue(Type type)
            {
                object value = null;

                if (type.IsValueType)
                    value = Activator.CreateInstance(type);
                else
                    value = null;

                return value;
            }

            // 获取指定类型的默认值.引用类型(包含String)的默认值为null
            private static T DefaultValue<T>()
            {
                return default(T);
            }

            //获取默认值
            private static object GetNullInternal(Type type)
            {
                if (type.IsValueType)
                {
                    if (type.IsEnum)
                    {
                        return GetNullInternal(Enum.GetUnderlyingType(type));
                    }
                    if (type.IsPrimitive)
                    {
                        if (type == typeof(int))
                        {
                            return 0;
                        }
                        if (type == typeof(double))
                        {
                            return 0.0;
                        }
                        if (type == typeof(short))
                        {
                            return (short)0;
                        }
                        if (type == typeof(sbyte))
                        {
                            return (sbyte)0;
                        }
                        if (type == typeof(long))
                        {
                            return 0L;
                        }
                        if (type == typeof(byte))
                        {
                            return (byte)0;
                        }
                        if (type == typeof(ushort))
                        {
                            return (ushort)0;
                        }
                        if (type == typeof(uint))
                        {
                            return 0;
                        }
                        if (type == typeof(ulong))
                        {
                            return (ulong)0L;
                        }
                        if (type == typeof(ulong))
                        {
                            return (ulong)0L;
                        }
                        if (type == typeof(float))
                        {
                            return 0f;
                        }
                        if (type == typeof(bool))
                        {
                            return false;
                        }
                        if (type == typeof(char))
                        {
                            return '\0';
                        }
                    }
                    else
                    {
                        if (type == typeof(DateTime))
                        {
                            return DateTime.MinValue;
                        }
                        if (type == typeof(decimal))
                        {
                            return 0M;
                        }
                        if (type == typeof(Guid))
                        {
                            return Guid.Empty;
                        }
                        if (type == typeof(TimeSpan))
                        {
                            return new TimeSpan(0, 0, 0);
                        }
                    }
                }
                return null;
            }



        // <summary>
        /// 复制控件。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="serializeObj"></param>
        /// <returns></returns>
        public static T GetObjectClone<T>(T serializeObj)
        {
            string base64String = SerializeObject<T>(serializeObj);
            return DeserializeObject<T>(base64String);
        }

        /// <summary>
        /// 序列化为Base64String。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="serializeObj"></param>
        /// <returns></returns>
        public static string SerializeObject<T>(T serializeObj)
        {
            string base64String = string.Empty;
            MemoryStream ms = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
            try
            {
                formatter.Serialize(ms, serializeObj);
                base64String = Convert.ToBase64String(ms.GetBuffer());
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to serialize. Reason: " + e.Message);
                throw;
            }
            finally
            {
                ms.Close();
            }
            return base64String;
        }

        /// <summary>
        /// 从Base64反序列化。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="base64String"></param>
        /// <returns></returns>
        public static T DeserializeObject<T>(string base64String)
        {
            MemoryStream ms = new MemoryStream(Convert.FromBase64String(base64String));
            BinaryFormatter formatter = new BinaryFormatter();

            try
            {
                // Deserialize the hashtable from the file and 
                // assign the reference to the local variable.
                return (T)formatter.Deserialize(ms);
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
                throw;
            }
            finally
            {
                ms.Close();
            }
        }
        #endregion
    }
    }