using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnivateProperties_API.Helpers.Attributes;

namespace UnivateProperties_API.Helpers
{
    public static class MyCommon
    {
        public static List<string> GetVisibleColumns<T>(T item) where T : new()
        {
            List<string> list = new List<string>();
            var type = item.GetType();
            var properties = type.GetProperties();
            var visibleProperties = properties.Where(x => x.GetCustomAttributes(false).Any(a => a.GetType() == typeof(VisibleInListViewAttribute) && ((a as VisibleInListViewAttribute).Value as bool?) == true)).ToList();
            visibleProperties.ForEach(x => list.Add(x.Name));
            return list;
        }

        public static string TenderUrl { get; set; }

        public static DateTime GetDateFromString(string value)
        {
            if (CheckDateDayFirst(value))
            {
                return new DateTime(Convert.ToInt32(value.Substring(6, 4)), Convert.ToInt32(value.Substring(3, 2)), Convert.ToInt32(value.Substring(0, 2)));
            }
            else if (CheckDateYearFirst(value))
            {
                return Convert.ToDateTime(value);
            }
            else return DateTime.MinValue;
        }

        public static bool CheckDateYearFirst(string value)
        {
            if(value.Length >= 10)
            {
                value = value.Substring(0, 10);
            }
            Regex reggie = new Regex(@"^\d{4}-((0[1-9])|(1[012]))-((0[1-9]|[12]\d)|3[01])$");
            return reggie.IsMatch(value);
        }

        public static bool CheckDateDayFirst(string value)
        {
            if (value.Length >= 10)
            {
                value = value.Substring(0, 10);
            }
            Regex reggie = new Regex(@"^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$");
            return reggie.IsMatch(value);
        }

        public static bool IsValidEmail(string item)
        {
            if (!string.IsNullOrEmpty(item))
            {
                Regex regex = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
                Match match = regex.Match(item);
                return match.Success;
            }
            else return false;
        }

        public static void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
        {
            if (password == null) throw new ArgumentNullException("password");
            if (string.IsNullOrWhiteSpace(password)) throw new ArgumentException("Value cannot be empty or whitespace only string.", "password");

            using (var hmac = new System.Security.Cryptography.HMACSHA512())
            {
                passwordSalt = hmac.Key;
                passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
            }
        }

        public static bool VerifyPasswordHash(string password, byte[] storedHash, byte[] storedSalt)
        {
            if (password == null) throw new ArgumentNullException("password");
            if (string.IsNullOrWhiteSpace(password)) throw new ArgumentException("Value cannot be empty or whitespace only string.", "password");
            if (storedHash.Length != 64) throw new ArgumentException("Invalid length of password hash (64 bytes expected).", "passwordHash");
            if (storedSalt.Length != 128) throw new ArgumentException("Invalid length of password salt (128 bytes expected).", "passwordHash");

            using (var hmac = new System.Security.Cryptography.HMACSHA512(storedSalt))
            {
                var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
                for (int i = 0; i < computedHash.Length; i++)
                {
                    if (computedHash[i] != storedHash[i]) return false;
                }
            }

            return true;
        }
    }
}