using System;
using System.Collections.Generic;
using System.DirectoryServices.ActiveDirectory;
using System.Net;
using System.Reflection;
using System.Xml;

using C4IT.DataHistoryProvider;
using C4IT.Logging;
using C4IT.Security;
using C4IT.XML;

using static C4IT.Logging.cLogManager;

namespace C4IT.DataHistoryProvider.Base.Modules.Citrix
{
    public class cDataHistoryConfigCitrix : IConfigNodeValidation
    {
        public bool IsValid { get; private set; } = false;
        public cDataHistoryScanTiming ScanTiming { get; private set; } = null;
        public cDataHistoryConfigCitrix(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            try
            {

                var XNode2 = XNode.SelectSingleNode("Citrix");
                if (!(XNode2 is XmlElement XCitrix))
                {
                    return;
                }

                Parser.EnterElement("Citrix");

                try
                {
                    ScanTiming = new cDataHistoryScanTiming(XCitrix, TimeSpan.FromHours(24), TimeSpan.FromMinutes(10), Parser);

                    Systems = cDataHistoryCitrixCloudTenant.LoadFromXml(XCitrix, Credentials, Parser);

                    if (Systems == null)
                        Systems = new List<cDataHistoryCitrixSystem>();

                    var _onPremSystems = cDataHistoryCitrixOnPrem.LoadFromXml(XCitrix, Credentials, Parser);
                    if (_onPremSystems != null)
                        Systems.AddRange(_onPremSystems);

                    IsValid = true;
                }
                finally
                {
                    Parser.LeaveElement("Citrix");
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }
        }

        public List<cDataHistoryCitrixSystem> Systems { get; private set; } = null;  //ToDo: Check all uses of the citrix systems to implement on prem and tenant specific handling if needed

    }

    public abstract class cDataHistoryCitrixSystem : cConfigNodeNamed
    {
        public cCredential Credential { get; private set; } = null;

        public Guid SiteID { get; set; } = Guid.Empty;

        public cDataHistoryCitrixSystem(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser) : base(XNode, Parser)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }

            try
            {
                if (!IsValid)
                    return;

                SiteID = cXmlParser.GetGuidFromXmlAttribute(XNode, "SiteID");

                var strCreds = cXmlParser.GetStringFromXmlAttribute(XNode, "Credential");
                if (!string.IsNullOrWhiteSpace(strCreds))
                {
                    if (Credentials.TryGetValue(strCreds, out var Cred))
                        Credential = Cred;
                }

                if (Credential == null)
                {
                    Parser.AddInvalidAttribute(XNode, null, "Credential");
                    return;
                }

                IsValid = true;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }
        }

    }

    public class cDataHistoryCitrixCloudTenant : cDataHistoryCitrixSystem
    {
        public string Domain { get; private set; } = "";

        public string TenantID { get; private set; } = String.Empty;

        internal cDataHistoryCitrixCloudTenant(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser) : base(XNode, Credentials, Parser)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            try
            {
                if (!IsValid)
                    return;

                Domain = cXmlParser.GetStringFromXmlAttribute(XNode, "Domain");
                if (string.IsNullOrWhiteSpace(Domain))
                {
                    Parser.AddInvalidAttribute(XNode, null, "Domain");
                    return;
                }

                TenantID = cXmlParser.GetStringFromXmlAttribute(XNode, "TenantID");
                if (TenantID == String.Empty)
                {
                    Parser.AddInvalidAttribute(XNode, Domain, "TenantID");
                    return;
                }


                IsValid = true;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }
        }

        internal static List<cDataHistoryCitrixSystem> LoadFromXml(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }

            var RetVal = new List<cDataHistoryCitrixSystem>();

            try
            {
                var XList = XNode.SelectNodes("Citrix-Cloud-Tenant");
                if (XList != null && XList.Count > 0)
                {
                    Parser.EnterElement("Citrix-Cloud-Tenant");
                    try
                    {
                        foreach (var Entry in XList)
                        {
                            if (!(Entry is XmlElement XEntry))
                                continue;

                            var Node = new cDataHistoryCitrixCloudTenant(XEntry, Credentials, Parser);
                            if (Node.IsValid)
                                RetVal.Add(Node);
                            Parser.SelectElementNext();
                        }
                    }
                    finally
                    {
                        Parser.LeaveElement("Citrix-Cloud-Tenant");
                    }
                }

                XList = XNode.SelectNodes("Citrix-OnPrem-System");
                if (XList != null && XList.Count > 0)
                {
                    Parser.EnterElement("Citrix-OnPrem-System");
                    try
                    {
                        foreach (var Entry in XList)
                        {
                            if (!(Entry is XmlElement XEntry))
                                continue;

                            var Node = new cDataHistoryCitrixOnPrem(XEntry, Credentials, Parser);
                            if (Node.IsValid)
                                RetVal.Add(Node);
                            Parser.SelectElementNext();
                        }
                    }
                    finally
                    {
                        Parser.LeaveElement("Citrix-OnPrem-System");
                    }
                }

            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }

            return RetVal;
        }
    }

    public class cDataHistoryCitrixOnPrem : cDataHistoryCitrixSystem
    {
        public string Server { get; private set; } = string.Empty;

        internal cDataHistoryCitrixOnPrem(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser) : base(XNode, Credentials, Parser)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }

            try
            {
                Server = cXmlParser.GetStringFromXmlAttribute(XNode, "Server");
                if (string.IsNullOrWhiteSpace(Server))
                {
                    Parser.AddInvalidAttribute(XNode, null, "Server");
                    return;
                }

                IsValid = true;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }
        }

        internal static List<cDataHistoryCitrixSystem> LoadFromXml(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }

            var RetVal = new List<cDataHistoryCitrixSystem>();

            try
            {
                var XList = XNode.SelectNodes("Citrix-OnPrem");
                if (XList != null && XList.Count > 0)
                {
                    Parser.EnterElement("Citrix-OnPrem");
                    try
                    {
                        foreach (var Entry in XList)
                        {
                            if (!(Entry is XmlElement XEntry))
                                continue;

                            var Node = new cDataHistoryCitrixOnPrem(XEntry, Credentials, Parser);
                            if (Node.IsValid)
                                RetVal.Add(Node);
                            Parser.SelectElementNext();
                        }
                    }
                    finally
                    {
                        Parser.LeaveElement("Citrix-OnPrem");
                    }
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }

            return RetVal;
        }
    }

}
