using System;
using System.DirectoryServices;
using System.Web;

namespace CD67.ModeleMVC.MVC.Internal
{ 
    public static class Utilisateur
    {
        /// <summary>
        /// Retourne une chaine prise dans l'AD correspondant au paramètre donné à la fonction :
        /// prenomnom , nom , prenom , email , login
        /// Une fois récupéré, la valeur est stocké en variable de session, et ne sera récupéré à nouveau depuis l'AD que si nécessaire.
        /// Si le paramètre ne correspond à aucun de ces cas, la fonction retourne une erreur.
        /// </summary>
        /// <param name="paramAD"></param>
        /// <returns>"Prenom Nom" ou "NOM" ou "Prenom" ou "email" ou "login"</returns>  
        public static string getInfoUtilisateur(string paramAD)
        {
            HttpContext context = HttpContext.Current;
            string resultat = "";
            string sessionIndex = "UserAD-" + paramAD;
            if (context.Session[sessionIndex] == null)
            {
                try
                {
                    DirectoryEntry userEntry = getUserEntry();
                    resultat = userEntry.Properties[paramAD].Value.ToString();
                    context.Session[sessionIndex] = resultat;
                }
                catch (NullReferenceException ex)
                {
                    throw new NullReferenceException("Paramètre AD non reconnu", ex);

                }
            }
            else
            {
                resultat = context.Session[sessionIndex].ToString();
            }
            return resultat;
        }
        /// <summary>
        /// Pour chacune des info standard que sont prenom_nom, prenom, nom, email et login,
        /// Renvoie la valeur qui lui correspond pour l'utilisateur courrant.
        /// L'info renvoyée dependra du paramètre donné à la fonction, qui devra correspondre à une des occurences de l'enum InfoStandard.
        /// </summary>
        /// <param name="infoStandard"></param>
        /// <returns name="resultat">Retourne l'information de l'AD correspondant au paramètre donné.</returns>
        public static string getInfoUtilisateur(InfoStandard infoStandard)
        {
            string resultat = "";

            switch (infoStandard)
            {
                case InfoStandard.nom_prenom:
                    resultat = getInfoUtilisateur("displayName");
                    break;
                case InfoStandard.prenom:
                    resultat = getInfoUtilisateur("givenName");
                    break;
                case InfoStandard.nom:
                    resultat = getInfoUtilisateur("sn").ToUpper();
                    break;
                case InfoStandard.email:
                    resultat = getInfoUtilisateur("mail");
                    break;
                case InfoStandard.login:
                    resultat = getInfoUtilisateur("sAMAccountName");
                    break;
            }

            return resultat;
        }

        public enum InfoStandard
        {
            nom_prenom,
            prenom,
            nom,
            email,
            login
        }


        /// <summary>
        /// Retourne l'entrée dans l'AD de l'utilisateur courant.
        /// Exemple d'accès aux propriétés : userEntry.Properties["givenName"].Value
        /// </summary>
        /// <returns>Entrée utilisateur</returns>
        private static DirectoryEntry getUserEntry()
        {
            try
            {
                string login = HttpContext.Current.User.Identity.Name.ToLower().Replace("cg67\\", "");
                if (login == null) throw new Exception("Impossible de récupérer le login de l'utilisateur courant.");

                DirectoryEntry ldap = new DirectoryEntry("LDAP://CG67.fr/OU=Organisation,dc=CG67,dc=fr", "LectureAD", "Adlecture!");
                DirectorySearcher searcher = new DirectorySearcher(ldap);

                searcher.Filter = $"(sAMAccountName={login})";
                SearchResult result = searcher.FindOne();

                DirectoryEntry userEntry = result.GetDirectoryEntry();
                return userEntry;
            }
            catch (NullReferenceException ex)
            {
                throw new Exception("Le nom d'utilisateur courant n'a pas été retrouvé dans l'AD.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Erreur dans la récupération des infos de l'utilisateur.", ex);
            }
        }
    }
}
