using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace Mammonth.Common {

    /// <summary>
    /// 数据验证类
    /// </summary>
    /// <remarks>
    /// 维护人：zhaoshunlu
    /// 最后修改：2013-11-4
    /// </remarks>
    public class DataValidator {

        /// <summary>
        /// 获取安全的字符串
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetSafeSqueryString(string str) {
            if (string.IsNullOrEmpty(str))
                return "";
            else
                return str.Trim().Replace(" ", "").Replace("'", "").Replace("%", "").Replace("--", "").Replace("or", "");
        }

        /// <summary>
        /// 日期格式验证 如：2013-06-01
        /// </summary>
        /// <param name="input"></param>
        /// <returns>bool</returns>
        /// <remarks>
        /// zhao 2013-11-01
        /// </remarks>
        public static bool IsDate(string input) {
            if (string.IsNullOrEmpty(input)) {
                return false;
            }
            return Regex.IsMatch(input,
             @"^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]" +
@"|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|" +
@"1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?" +
@"2-(0?[1-9]|1\d|2[0-9]))|(((1[6-9]|[2-9]\d)(0[48]|[2468]" +
@"[048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$");

        }
        /// <summary>  
        /// 是否为时间型字符串  
        /// </summary>  
        /// <param name="source">时间字符串(15:00:00)</param>  
        /// <returns></returns>  
        public static bool IsTime(string input) {
            if (string.IsNullOrEmpty(input)) {
                return false;
            }
            return Regex.IsMatch(input, @"^((20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d)$");
        }

        /// <summary>  
        /// 是否为日期+时间型字符串  
        /// </summary>  
        /// <param name="source"></param>  
        /// <returns></returns>  
        public static bool IsDateTime(string input) {
            if (string.IsNullOrEmpty(input)) {
                return false;
            }
            return Regex.IsMatch(input,
@"^(((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?" +
@"[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?" +
@"[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]" +
@"|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-" +
@"9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[" +
@"2468][048]|[3579][26])00))-0?2-29-)) (20|21|22|23" +
@"|[0-1]?\d):[0-5]?\d:[0-5]?\d)$ ");
        }

        /// <summary>
        /// 实数验证
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsDecimal(string input) {
            if (string.IsNullOrEmpty(input)) {
                return false;
            }
            return Regex.IsMatch(input, "^[0-9]+[.]?[0-9]+$");
        }

        /// <summary>
        /// 带符号的实数验证
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsDecimalSign(string input) {
            if (string.IsNullOrEmpty(input)) {
                return false;
            }
            return Regex.IsMatch(input, "^[+-]?[0-9]+[.]?[0-9]+$");
        }

        /// <summary>
        /// 正整数验证
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsNumber(string input) {
            if (string.IsNullOrEmpty(input)) {
                return false;
            }
            return Regex.IsMatch(input, "^[0-9]+$");
        }

        /// <summary>
        /// 整数验证
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsNumberSign(string input) {
            if (string.IsNullOrEmpty(input)) {
                return false;
            }
            return Regex.IsMatch(input, "^[+-]?[0-9]+$");
        }

        /// <summary>
        /// 邮编验证
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsPostCode(string input) {
            return (IsNumber(input) && (input.Length == 6));
        }

        /// <summary>
        /// 邮箱地址格式验证
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsEmail(string input) {
            if (string.IsNullOrEmpty(input)) {
                return false;
            }
            return Regex.IsMatch(input, @"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$");
        }

        /// <summary>
        /// IP地址验证
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsIP(string input) {
            return (!string.IsNullOrEmpty(input) && Regex.IsMatch(input.Trim(), @"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$"));
        }

        /// <summary>
        /// URL验证
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsUrl(string input) {
            if (string.IsNullOrEmpty(input)) {
                return false;
            }
            return Regex.IsMatch(input, @"^http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?$");
        }

        /// <summary>
        /// 区号验证
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsAreaCode(string input) {
            return ((IsNumber(input) && (input.Length >= 3)) && (input.Length <= 5));
        }

        /// <summary>
        /// 用户名格式验证,长度[0,20],不能含有\\/\"[]:|<>+=;,?*@
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public static bool IsValidUserName(string userName) {
            if (string.IsNullOrEmpty(userName)) {
                return false;
            }
            if (userName.Length > 20) {
                return false;
            }
            if (userName.Trim().Length == 0) {
                return false;
            }
            if (userName.Trim(new char[] { '.' }).Length == 0) {
                return false;
            }
            string str = "\\/\"[]:|<>+=;,?*@";
            for (int i = 0; i < userName.Length; i++) {
                if (str.IndexOf(userName[i]) >= 0) {
                    return false;
                }
            }
            return true;
        }
/// <summary>
        /// 比较同一类型的两个对象实例的属性值有哪些不同
        /// </summary>
        /// <param name="oldModel">旧对象</param>
        /// <param name="newModel">新对象</param>
        /// <param name="AllKeys">特别指定需要比较的属性键集合,如果为null或者长度为0那么就比较所有属性，默认为null</param>
        /// <param name="FilterKeys">特别指定需要排除的属性键集合,默认为null</param>
        /// <param name="BackDifValue">是否返回对比结果</param>
        /// <returns>返回不同的属性名称及两者内容 键值对</returns>
        /// <remarks>
        /// 创建：zhaoshunlu 日期：2014-10-11
        /// </remarks>
        /// <value>Hashtable</value>
        public static Hashtable ComparisonDifferent<T>(T oldModel, T newModel, string[] CheckKeys = null, string[] FilterKeys = null, bool BackDifValue = false)
        {
            //
            Hashtable lists = new Hashtable();
            if (oldModel == null || newModel == null) return lists;
            //
            Type type = typeof(T);
            //初始化属性组
            PropertyInfo[] props = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
            //遍历属性比较(要是一个一个属性比较真心累)
            for (int i = 0; i < props.Length; i++)
            {
                //只处理在指定集合中的属性
                if (CheckKeys == null || (CheckKeys != null && CheckKeys.Length == 0) || CheckKeys.Contains(props[i].Name))
                {
                    // 
                    //跳过排除的项
                    if (!(FilterKeys != null && FilterKeys.Contains(props[i].Name)))
                    {
                        //跳过 Ilist~1 等集合属性
                        if (props[i].PropertyType.Name != "IList`1")
                        {
                            //
                            object oldfd = props[i].GetValue(oldModel, null);
                            object newfd = props[i].GetValue(newModel, null);

                            //判断新旧值是否相同
                            if (oldfd != null && newfd != null && !oldfd.Equals(newfd))
                            {
                                if (BackDifValue)
                                {
                                    //为了做修改日记，要对比结果
                                    //获取模型自定义属性
                                    object[] cab = props[i].GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.DisplayAttribute), false);
                                    var caption = (cab != null && cab.Length > 0) ? ((System.ComponentModel.DataAnnotations.DisplayAttribute)cab[0]).Name : "";
                                    //保存日记代码
                                    Hashtable hasChg = new Hashtable();                                  
                                    hasChg["Name"] = props[i].Name; //字段名称如：Name
                                    hasChg["Caption"] = caption;    //字段别名如：姓名,通过反射获取到它，哦哦哦                           
                                    hasChg["OldVal"] = oldfd;       //原内容
                                    hasChg["NewVal"] = newfd;       //新内容
                                    //
                                    //加入键值对
                                    lists.Add(props[i].Name, hasChg);
                                }
                                else
                                {
                                    lists.Add(props[i].Name, null);
                                }
                            }
                        }
                    }

                }
            }
            //
            return lists;
        }
        

        #region 身份证验证 作者:yangguoji 添加时间:2014年3月14日 11:22:44
        /// <summary>
        /// 身份证验证,支持18位和15位身份证
        /// 作者:yangguoji
        /// 时间:2014-03-14 11:23:35
        /// </summary>
        /// <param name="Id">身份证号</param>
        /// <returns></returns>
        public static bool CheckIDCard(string Id) {
            if (Id.Length == 18) {
                return CheckIDCard18(Id);
            } else if (Id.Length == 15) {
                return CheckIDCard15(Id);
            } else {
                return false;
            }
        }
        /// <summary>
        /// 18位身份证验证
        /// 作者:yangguoji
        /// 时间:2014-03-14 11:23:35
        /// </summary>
        /// <param name="Id">身份证号</param>
        /// <returns></returns>
        private static bool CheckIDCard18(string Id) {
            long n = 0;
            if (long.TryParse(Id.Remove(17), out n) == false || n < Math.Pow(10, 16) || long.TryParse(Id.Replace('x', '0').Replace('X', '0'), out n) == false) {
                return false;//数字验证
            }
            string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";
            if (address.IndexOf(Id.Remove(2)) == -1) {
                return false;//省份验证
            }
            string birth = Id.Substring(6, 8).Insert(6, "-").Insert(4, "-");
            DateTime time = new DateTime();
            if (DateTime.TryParse(birth, out time) == false) {
                return false;//生日验证
            }
            string[] arrVarifyCode = ("1,0,x,9,8,7,6,5,4,3,2").Split(',');
            string[] Wi = ("7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2").Split(',');
            char[] Ai = Id.Remove(17).ToCharArray();
            int sum = 0;
            for (int i = 0; i < 17; i++) {
                sum += int.Parse(Wi[i]) * int.Parse(Ai[i].ToString());
            }
            int y = -1;
            Math.DivRem(sum, 11, out y);
            if (arrVarifyCode[y] != Id.Substring(17, 1).ToLower()) {
                return false;//校验码验证
            }
            return true;//符合GB11643-1999标准
        }
        /// <summary>
        /// 15位身份证验证
        /// 作者:yangguoji
        /// 时间:2014-03-14 11:23:35
        /// </summary>
        /// <param name="Id">身份证号</param>
        /// <returns></returns>
        private static bool CheckIDCard15(string Id) {
            long n = 0;
            if (long.TryParse(Id, out n) == false || n < Math.Pow(10, 14)) {
                return false;//数字验证
            }
            string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";
            if (address.IndexOf(Id.Remove(2)) == -1) {
                return false;//省份验证
            }
            string birth = Id.Substring(6, 6).Insert(4, "-").Insert(2, "-");
            DateTime time = new DateTime();
            if (DateTime.TryParse(birth, out time) == false) {
                return false;//生日验证
            }
            return true;//符合15位身份证标准
        }
        #endregion
    }
}