using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;

namespace CommonFunc
{
    public class ValidationFunc
    {
        public PropertyInfo GetPropertyInfo(ViewDataDictionary viewData)
        {
            var metadata = viewData.ModelMetadata;
            var prop = metadata.ContainerType.GetProperty(metadata.PropertyName);
            return prop;
        }
        public object[] CollectAllAttributes<T>()
        {
            var listOfAttributes = new List<object>();
            foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
            {
                listOfAttributes.AddRange(propertyInfo.GetCustomAttributes(false));
                var name = propertyInfo.Name;
            }
            return listOfAttributes.ToArray();
        }
        /*validate Parameters by Provide class name and list of parameters in "parameters"*/
        public static validate ValidateModelData<T>(object K, params object[] Parameters)
        {
            validate vm = new validate();
            bool result = true;
            var model1 = typeof(T).Name;
            //Model Name
            var name = typeof(T).Name.Replace("Model", "ViewModel");
            name = Char.ToLowerInvariant(name[0]) + name.Substring(1);
            string Message = "";
            foreach (var prop in typeof(T).GetProperties())
            {
                // Variable Array with properties
                object[] attrs = prop.GetCustomAttributes(false);
                //Variable name of Model
                string VariableName = prop.Name;

                string conds = "";
                //check if variable exist in parameter for validation
                if ((Parameters.Length > 0 && Parameters.Contains(VariableName)) || (Parameters.Length == 0))
                {
                    //DataType of Variable
                    var datatype = prop.PropertyType.Name.ToString().Trim();
                    //Check variable for nulls
                    if (attrs == null || attrs.Length == 0)
                        continue;

                    int i = 1;
                    bool isHtmlAttribute = false;
                    foreach (Attribute attr in attrs)
                    {
                        if (attr is AllowHtmlAttribute)
                        {
                            isHtmlAttribute = true;
                        }
                    }
                    foreach (Attribute attr in attrs)
                    {
                        string Variable = K.GetType().Name.ToString();
                        //Values of Variable
                        var values = Convert.ToString(K.GetType().GetProperty(VariableName).GetValue(K, null));
                        if ((datatype.ToLower() == "httppostedfilebase" && values != null && values != "") || (datatype.ToLower() != "httppostedfilebase"))
                        {

                            string ErrorMessage = (attr.GetType().GetProperty("ErrorMessage") != null) ? Convert.ToString(attr.GetType().GetProperty("ErrorMessage").GetValue(attr, null)) : "";
                            //required field validator
                            if (datatype.ToLower() == "int")
                            {
                                if (!CheckFunc.IsNumeric(values))
                                {
                                    conds += "<li>" + VariableName + ": is not numeric</li>";
                                    result = false;
                                }
                            }
                            if (datatype.ToLower() == "double" || datatype.ToLower() == "float")
                            {
                                if (!CheckFunc.IsDouble(values))
                                {
                                    conds += "<li>" + VariableName + ": is not decimal or integer</li>";
                                    result = false;
                                }
                            }
                            if (attr is RequiredAttribute)
                            {
                                if (values == null || values == "")
                                {
                                    conds += "<li>" + VariableName + ": " + ErrorMessage + "</li>";
                                    result = false;
                                }
                                if (datatype.ToLower() == "int")
                                {
                                    if (Convert.ToInt32(values) <= 0)
                                    {
                                        conds += "<li>" + VariableName + ": " + ErrorMessage + "</li>";
                                        result = false;
                                    }
                                }
                                if (datatype.ToLower() == "double")
                                {
                                    
                                    if (Convert.ToDouble(values) <= 0)
                                    {
                                        conds += "<li>" + VariableName + ": " + ErrorMessage + "</li>";
                                        result = false;
                                    }
                                }

                            }
                            //if Variable declared with [AllowHtml]
                            if (isHtmlAttribute == true)
                            {
                                if (!SpecialCharacterFunc.TextAreaString(HttpUtility.HtmlDecode(values)))
                                {
                                    conds += "<li>" + VariableName + ": Special Character not Allowed</li>";
                                    result = false;
                                }
                            }

                            else
                            {
                                //Variable not declared as [AllowHtml]

                                if (isHtmlAttribute == false)
                                {
                                    if (VariableName.ToLower().Contains("title") || VariableName.ToLower().Contains("heading"))
                                    {
                                        if (!SpecialCharacterFunc.Title(values))
                                        {
                                            conds += "<li>" + VariableName + ": Special Character not Allowed</li>";
                                            result = false;
                                        }
                                    }
                                    else if (VariableName.ToLower().Contains("alias"))
                                    {
                                        if (!SpecialCharacterFunc.Alias(values))
                                        {
                                            conds += "<li>" + VariableName + ": Special Character not Allowed</li>";
                                            result = false;
                                        }
                                    }
                                    else if (!SpecialCharacterFunc.TextBoxString(values))
                                    {
                                        conds += "<li>" + VariableName + ": Special Character not Allowed</li>";
                                        result = false;
                                    }
                                }
                            }
                            if (attr is RangeAttribute)
                            {
                                if (Int32.Parse(values) < Int32.Parse((attr as RangeAttribute).Minimum.ToString()) && Int32.Parse(values) > Int32.Parse((attr as RangeAttribute).Minimum.ToString()))
                                    conds += "<li>" + VariableName + " Min Range should be " + (attr as RangeAttribute).Minimum + " and Max Range should be " + (attr as RangeAttribute).Maximum + "</li>";
                                result = false;
                            }
                            //MinLenght Validator
                            if (attr is MinLengthAttribute)
                            {
                                if ((attr as MinLengthAttribute).Length > values.Length)
                                {
                                    conds += "<li>" + VariableName + " minLength should be " + (attr as MinLengthAttribute).Length + "</li>";

                                    result = false;
                                }
                            }
                            //MaxLenght Validator
                            if (attr is MaxLengthAttribute)
                            {
                                if ((attr as MaxLengthAttribute).Length < values.Length)
                                {
                                    conds += "<li>" + VariableName + " maxLength max length " + (attr as MaxLengthAttribute).Length + "</li>";
                                    result = false;
                                }
                            }
                            //Email Validator
                            if (attr is EmailAddressAttribute)
                            {
                                if (!CheckFunc.IsEmail(values))
                                {
                                    conds += "<li>" + VariableName + ": " + ErrorMessage + "</li>";
                                    result = false;
                                }
                            }

                            //RegularExpression Validator
                            if (attr is RegularExpressionAttribute)
                            {

                                string pattern = Convert.ToString((attr as RegularExpressionAttribute).Pattern);
                                //pattern = pattern.Replace("(", "").Replace(")", "");
                                Match m = Regex.Match(values, @"" + pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
                                if (m.Success == false)
                                {
                                    conds += "<li>" + VariableName + ": " + ErrorMessage + "</li>";
                                    result = false;
                                }
                            }
                            //StringLength Validator
                            if (attr is StringLengthAttribute)
                            {
                                //validate string between min and max length
                                bool results = lengthValidate(values, (attr as StringLengthAttribute).MinimumLength, (attr as StringLengthAttribute).MaximumLength);
                                if (results == false)
                                {
                                    conds += "<li>" + VariableName + ": " + ErrorMessage + "</li>";
                                    result = false;
                                }
                            }
                        }
                        i++;
                    }
                }
                // Add all validation error
                if (conds.Length > 0)
                    Message += String.Format("{0}", conds);
            }
            vm.isValid = result;
            vm.Message = Message;
            return vm;
        }

        public static bool lengthValidate(string values, int minLength, int maxLength)
        {
            bool results = true;
            if (minLength > 0 && maxLength > 0)
            {
                if (values.Length < minLength || values.Length > maxLength)
                {
                    results = false;
                }
            }
            if (minLength == 0 && maxLength > 0)
            {
                if (values.Length > maxLength)
                {
                    results = false;
                }
            }
            if (minLength > 0 && maxLength == 0)
            {
                if (values.Length < minLength)
                {
                    results = false;
                }
            }
            return results;
        }
        public string DefaultValidation(object k)
        {
            var validationContext = new ValidationContext(k, serviceProvider: null, items: null);
            var validationResults = new List<ValidationResult>();
            var validate = new List<ValidationAttribute>();
            var isValid = Validator.TryValidateObject(k, validationContext, validationResults);
            var type = k.GetType().GetProperty("flBackground");
            StringBuilder opStatus = new StringBuilder();
            // If there any exception return them in the return result
            if (!isValid)
            {
                foreach (ValidationResult message in validationResults)
                {
                    opStatus.Append(message.ErrorMessage);
                }
            }
            return opStatus.ToString();
        }
        /*validate Image with File format and File size width and height*/
        public static validate ImageValidate(HttpPostedFileBase fileMainImage, string format = "", float width = 0, float height = 0)
        {
            validate vm = new validate();
            bool result = true;
            format = (format == "") ? ".png, .jpg, .jpeg, .gif" : format;
            if (fileMainImage != null && fileMainImage.ContentLength > 0)
            {
                string bannerimageTemp = "";
                if (fileMainImage.CheckUploadFileExt(format) != "success")
                {
                    vm.Message = "Images - Invalid file format ! (Allowed | " + format + " |)";
                    vm.isValid = false;
                    return vm;
                }
                if (width != 0 || height != 0)
                {
                    System.Drawing.Image UploadedImage = System.Drawing.Image.FromStream(fileMainImage.InputStream);
                    float UploadedImageWidth = UploadedImage.PhysicalDimension.Width;
                    float UploadedImageHeight = UploadedImage.PhysicalDimension.Height;
                    if (width != 0 && height == 0)
                    {
                        if (UploadedImageWidth != width)
                        {
                            vm.Message = "Invalid width ! (Allowed | width " + width + ")";
                            vm.isValid = false;
                            return vm;
                        }
                    }
                    if (width == 0 && height != 0)
                    {
                        if (UploadedImageHeight != height)
                        {
                            vm.Message = "Invalid height ! (Allowed | height " + height + ")";
                            vm.isValid = false;
                            return vm;
                        }
                    }
                    //if (width != 0 && height != 0)
                    //{
                    //    vm.Message = "Invalid Size ! (Allowed | " + width + " * " + height + ")";
                    //    vm.isValid = false;
                    //    return vm;
                    //}
                }
                bannerimageTemp = System.IO.Path.GetFileNameWithoutExtension(fileMainImage.FileName);
                if (!SpecialCharacterFunc.SpecialCharFileNameString(bannerimageTemp))
                {
                    vm.Message = "Image name has some invalid char. This name will use for alt, Title tags.";
                    vm.isValid = false;
                    return vm;
                }

            }
            else
            {
                vm.Message = "No image selected";
                vm.isValid = false;
                return vm;
            }
            return vm;
        }
        /*validate Image with File format and File size by maintaining ratio of width and height*/
        public static validate ImageValidateRatio(HttpPostedFileBase fileMainImage, float width, float height, string format = "")
        {
            validate vm = new validate();
            bool result = true;
            format = (format == "") ? ".png, .jpg, .jpeg, .gif" : format;
            if (fileMainImage != null && fileMainImage.ContentLength > 0)
            {
                string bannerimageTemp = "";
                if (fileMainImage.CheckUploadFileExt(".jpg, .jpeg") != "success")
                {
                    vm.Message = "Images - Invalid file format ! (Allowed | *.jpg,*.jpeg |)";
                    vm.isValid = false;
                    return vm;
                }
                if (width != 0 || height != 0)
                {
                    System.Drawing.Image UploadedImage = System.Drawing.Image.FromStream(fileMainImage.InputStream);
                    float UploadedImageWidth = UploadedImage.PhysicalDimension.Width;
                    float UploadedImageHeight = UploadedImage.PhysicalDimension.Height;

                    if (UploadedImageWidth / UploadedImageHeight != width / height)
                    {
                        vm.Message = "Invalid image ration ! (Allowed | " + width + " * " + height + " (" + width / height + ") )";
                        vm.isValid = false;
                        return vm;
                    }
                }
                bannerimageTemp = System.IO.Path.GetFileNameWithoutExtension(fileMainImage.FileName);
                if (!SpecialCharacterFunc.SpecialCharFileNameString(bannerimageTemp))
                {
                    vm.Message = "Image name has some invalid char. This name will use for alt, Title tags.";
                    vm.isValid = false;
                    return vm;
                }

            }
            else
            {
                vm.Message = "No image selected";
                vm.isValid = false;
                return vm;
            }
            return vm;
        }
        /*validate Image with File format and Min File size width and height and by maintaining ratio of width and height*/
        public static validate ImageValidateRatioMinSize(HttpPostedFileBase fileMainImage, string format = "", int width = 0, int height = 0)
        {
            validate vm = new validate();
            bool result = true;
            format = (format == "") ? ".png, .jpg, .jpeg, .gif" : format;
            if (fileMainImage != null && fileMainImage.ContentLength > 0)
            {
                string bannerimageTemp = "";
                if (fileMainImage.CheckUploadFileExt(".jpg, .jpeg") != "success")
                {
                    vm.Message = "Images - Invalid file format ! (Allowed | *.jpg,*.jpeg |)";
                    vm.isValid = false;
                    return vm;
                }
                if (width != 0 || height != 0)
                {
                    System.Drawing.Image UploadedImage = System.Drawing.Image.FromStream(fileMainImage.InputStream);
                    float UploadedImageWidth = UploadedImage.PhysicalDimension.Width;
                    float UploadedImageHeight = UploadedImage.PhysicalDimension.Height;
                    if (UploadedImageWidth < width && UploadedImageHeight < height)
                    {
                        vm.Message = "Invalid Size ! (Allowed Min Size | " + width + " * " + height + ")";
                        vm.isValid = false;
                        return vm;
                    }
                    if (UploadedImageWidth / UploadedImageHeight != width / height)
                    {
                        vm.Message = "Invalid image ration ! (Allowed | " + width + " * " + height + " (" + width / height + ") )";
                        vm.isValid = false;
                        return vm;
                    }
                    if (UploadedImageWidth / UploadedImageHeight != width / height)
                    {
                        vm.Message = "Invalid image ration ! (Allowed | " + width + " * " + height + " (" + width / height + ") )";
                        vm.isValid = false;
                        return vm;
                    }
                }
                bannerimageTemp = System.IO.Path.GetFileNameWithoutExtension(fileMainImage.FileName);
                if (!SpecialCharacterFunc.SpecialCharFileNameString(bannerimageTemp))
                {
                    vm.Message = "Image name has some invalid char. This name will use for alt, Title tags.";
                    vm.isValid = false;
                    return vm;
                }

            }
            else
            {
                vm.Message = "No image selected";
                vm.isValid = false;
                return vm;
            }
            return vm;
        }
        /*validate Multiple Image with File format and File size width and height*/
        public static validate MultiImageValidate(HttpFileCollectionBase fileMainImage, string format = "", int maximage = 0, float width = 0, float height = 0)
        {
            validate vm = new validate();
            bool result = true;
            format = (format == "") ? ".png, .jpg, .jpeg, .gif" : format;
            if (fileMainImage != null && fileMainImage.Count > 0)
            {
                if (maximage > 0)
                {
                    if (fileMainImage.Count > maximage)
                    {
                        vm.Message = "Images - Max " + maximage + " images are allowed!";
                        vm.isValid = false;
                        return vm;
                    }
                }
                for (int m = 0; m < fileMainImage.Count; m++)
                {
                    HttpPostedFileBase file = fileMainImage[m];
                    if (file.CheckUploadFileExt(".jpg, .jpeg") != "success")
                    {
                        vm.Message = "Images - Invalid file format ! (Allowed | *.jpg,*.jpeg |)";
                        vm.isValid = false;
                        return vm;
                    }
                    if (width != 0 || height != 0)
                    {
                        System.Drawing.Image UploadedImage = System.Drawing.Image.FromStream(file.InputStream);
                        float UploadedImageWidth = UploadedImage.PhysicalDimension.Width;
                        float UploadedImageHeight = UploadedImage.PhysicalDimension.Height;
                        if (width != 0 && height == 0)
                        {
                            if (UploadedImageWidth != width)
                            {
                                vm.Message = "Invalid width ! (Allowed | width " + width + ")";
                                vm.isValid = false;
                                return vm;
                            }
                        }
                        if (width == 0 && height != 0)
                        {
                            if (UploadedImageHeight != height)
                            {
                                vm.Message = "Invalid height ! (Allowed | height " + height + ")";
                                vm.isValid = false;
                                return vm;
                            }
                        }
                    }
                    string ImageName = System.IO.Path.GetFileNameWithoutExtension(file.FileName);
                    if (!SpecialCharacterFunc.SpecialCharFileNameString(ImageName))
                    {
                        vm.Message = "Image name has some invalid char. This name will use for alt, Title tags.";
                        vm.isValid = false;
                        return vm;
                    }
                    //result.Add(file.FileName);
                }

            }
            return vm;
        }
        /*validate Multiple Image with File format and Min File size width and height and by maintaining ratio of width and height*/
        public static validate MultiImageValidateRatioMinSize(HttpFileCollectionBase fileMainImage, string format = "", int maximage = 0, float width = 0, float height = 0)
        {
            validate vm = new validate();
            bool result = true;
            format = (format == "") ? ".png, .jpg, .jpeg, .gif" : format;
            if (fileMainImage != null && fileMainImage.Count > 0)
            {
                if (maximage > 0)
                {
                    if (fileMainImage.Count > maximage)
                    {
                        vm.Message = "Images - Max " + maximage + " images are allowed!";
                        vm.isValid = false;
                        return vm;
                    }
                }
                for (int m = 0; m < fileMainImage.Count; m++)
                {
                    HttpPostedFileBase file = fileMainImage[m];
                    if (file.CheckUploadFileExt(".jpg, .jpeg") != "success")
                    {
                        vm.Message = "Images - Invalid file format ! (Allowed | *.jpg,*.jpeg |)";
                        vm.isValid = false;
                        return vm;
                    }
                    if (width != 0 || height != 0)
                    {
                        System.Drawing.Image UploadedImage = System.Drawing.Image.FromStream(file.InputStream);
                        float UploadedImageWidth = UploadedImage.PhysicalDimension.Width;
                        float UploadedImageHeight = UploadedImage.PhysicalDimension.Height;
                        if (UploadedImageWidth < width && UploadedImageHeight < height)
                        {
                            vm.Message = "Invalid Size ! (Allowed Min Size | " + width + " * " + height + ")";
                            vm.isValid = false;
                            return vm;
                        }
                        if (UploadedImageWidth / UploadedImageHeight != width / height)
                        {
                            vm.Message = "Invalid image ration ! (Allowed | " + width + " * " + height + " (" + width / height + ") )";
                            vm.isValid = false;
                            return vm;
                        }
                        if (UploadedImageWidth / UploadedImageHeight != width / height)
                        {
                            vm.Message = "Invalid image ration ! (Allowed | " + width + " * " + height + " (" + width / height + ") )";
                            vm.isValid = false;
                            return vm;
                        }
                    }
                    string ImageName = System.IO.Path.GetFileNameWithoutExtension(file.FileName);
                    if (!SpecialCharacterFunc.SpecialCharFileNameString(ImageName))
                    {
                        vm.Message = "Image name has some invalid char. This name will use for alt, Title tags.";
                        vm.isValid = false;
                        return vm;
                    }
                    //result.Add(file.FileName);
                }

            }
            return vm;
        }
        /*validate password complexity for length, case sensitivity, numeric,special character, any pattern not required*/
        public static validate PasswordComplexity(string password, int Length, string patternsToEscape = "", bool caseSensitivty = true, bool numericDigits = true, bool SpecialCharacter = true)
        {
            validate vl = new validate();
            bool valid = true;
            string result = "";
            if (password.Length <= Length)
            {
                valid = false;

            }
            if (caseSensitivty == true)
            {

                int hasUpperCase = Regex.Match(password, "[A-Z]").Length;
                if (hasUpperCase < 0)
                {
                    valid = false;
                    result += " , one upper case";
                }
                int hasLowerCase = Regex.Match(password, "[A-Z]").Length;
                if (hasLowerCase <= 0)
                {
                    valid = false;
                    result += " , one lower case";
                }
            }
            if (numericDigits == true)
            {
                int hasNumbers = Regex.Match(password, "[0-9]").Length;
                if (hasNumbers <= 0)
                {
                    valid = false;
                    result += " , one numeric";
                }
            }
            if (SpecialCharacter == true)
            {
                int hasSpecial = Regex.Match(password, "[!@#$&*]").Length;
                if (hasSpecial <= 0)
                {
                    valid = false;
                    result += " , one special character";
                }
            }
            if (patternsToEscape != "")
            {
                int hasLowerCase = Regex.Match(password, @"" + patternsToEscape + "").Length;
                if (hasLowerCase <= 0)
                {
                    valid = false;
                }
            }
            vl.isValid = valid;
            string mesg = (result != "") ? "and must has atleast " + result.Substring(1, result.Length - 1) : "";
            vl.Message = "Password must has " + Length + " character length " + mesg;
            return vl;
        }
    }
}


