using System;
using Microsoft.MetadirectoryServices;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using System.Xml;
using System.Diagnostics;
using System.Linq;
using System.Globalization;

namespace Mms_Metaverse
{
    /// <summary>
    /// Summary description for MVExtensionObject.
    /// </summary>
    public class MVExtensionObject : IMVSynchronization
    {
        //DN de l'OU Active Directory contenant les utilisateurs
        private string userContainerName;

        public MVExtensionObject()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        void IMVSynchronization.Initialize()
        {
            //
            // TODO: write initialization code
            //
            //Nom du fichier xml
            const string XML_CONFIG_FILE = @"\Rules-config.xml";
            XmlDocument config = new XmlDocument();
            string dir = Utils.ExtensionsDirectory;
            try
            {
                //Récupération du fichier de trace
                config.Load(dir + XML_CONFIG_FILE);
                //Récupération du noeud contenant les paramètres activedirectory des utilisateurs
                XmlNode adUserNode = config.SelectSingleNode
                    ("rules-extension-properties/user/activedirectory");
                //Récupération de l'OU Active Directory contenant les utilisateurs 
                XmlNode userContainer = adUserNode.SelectSingleNode("container");
                userContainerName = userContainer.InnerText;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        void IMVSynchronization.Terminate()
        {
            //
            // TODO: Add termination logic here
            //
        }

        void IMVSynchronization.Provision(MVEntry mventry)
        {
            //S'il s'agit d'un objet de type person
            if (mventry.ObjectType == "person")
            {
                //Vérification de la présence d'un Common Name
                if (!mventry["cn"].IsPresent)
                {
                    var message = "L'objet " + mventry.ObjectID + " de la metaverse n'a pas de CN.";
                    throw new AttributeNotPresentException("cn");
                }

                //Vérification de la présence d'un SamAccountName
                if (!mventry["accountname"].IsPresent)
                {
                    var message = "L'objet " + mventry.ObjectID + " de la metaverse n'a pas de samAccountName.";
                    throw new AttributeNotPresentException("sAMAccountName");
                }

                //Vérification de la présence d'un displayName
                if (!mventry["displayName"].IsPresent)
                {
                    var message = "L'objet " + mventry.ObjectID + " de la metaverse n'a pas de displayName.";
                    throw new AttributeNotPresentException("displayName");
                }


                //Récupération des connecteurs existants.
                ConnectedMA managementAgent = mventry.ConnectedMAs["Active Directory MA"];
                int connectors = managementAgent.Connectors.Count;

                //Construction du DN.
                string container = userContainerName;
                string rdn = "CN=" + mventry["cn"].Value;
                ReferenceValue dn = managementAgent.EscapeDNComponent(rdn).Concat(container);
                int index = 0;
                bool uniqueDN = false;

                //S'il n'y a pas de connecteur création d'un 
                //nouveau connecteur et définition des attributs dans le CS AD.      
                if (0 == connectors)
                {
                    while (!uniqueDN)
                    {
                        try
                        {
                            // Création du connecteur dans le management agent AD
                            CSEntry csentry = managementAgent.Connectors.StartNewConnector("person");
                            csentry.DN = dn;
                            csentry["cn"].Value = mventry["cn"].Value;
                            csentry["sAMAccountName"].Value = mventry["accountname"].Value;
                            csentry["displayName"].Value = mventry["displayName"].Value;

                            csentry.CommitNewConnector();
                            uniqueDN = true;
                        }
                        // Creation d'un DN avec un suffixe numérique si le DN existe déjà (afin d'obtenir un DN unique)
                        catch (ObjectAlreadyExistsException)
                        {
                            rdn = "CN=" + mventry["cn"].Value + index.ToString();
                            dn = managementAgent.EscapeDNComponent(rdn).Concat(container);
                            index++;
                            uniqueDN = false;
                        }
                        catch (Exception e)
                        {
                            var message = "Une erreur s'est produite pendant le provisioning de l'objet " + mventry["cn"].Value + ". Message d'erreur : " + e.Message;
                            throw new ExtensionException(e.Message);
                        }
                    }
                }
            }

        }

        bool IMVSynchronization.ShouldDeleteFromMV(CSEntry csentry, MVEntry mventry)
        {
            //
            // TODO: Add MV deletion logic here
            //
            return false;
        }
    }
}