using Microsoft.Win32;
using System;
using System.Configuration;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;

namespace T2_SVR
{
    public class T2ServerManager
    {
        private string _dbConnectionName;
        private string _dBconnectionString;
        private string _lmPassword;
        private Exception _lmPingException;
        private string _lmT2ServerIPV4Addr;
        private string _lmT2ServerName;
        private string ctIPRefreshName = "T2DSIPRefresh";
        private string ctIPRegName = "T2DSIPAddress";
        private string ldIPRefresh = DateTime.Now.AddDays(1.0).ToShortDateString();
        // Methods
        public T2ServerManager(string ConnectionStringName)
        {
            this._dbConnectionName = ConnectionStringName;
            this.InitReg();
            this._lmT2ServerName = "W7USMJ02GA81D.NAM.GAD.SCHNEIDER-ELECTRIC.COM";
            this._lmT2ServerIPV4Addr = this.RegIPV4Address;
            this._lmPassword = ";PASSWORD=P85T2DS@01";
            this.BuildConnectionString();
            this.Search();
        }

        private void BuildConnectionString()
        {
            string connectionProvider = ConfigurationManager.ConnectionStrings[this._dbConnectionName].ProviderName;
            string connectionString = ConfigurationManager.ConnectionStrings[this._dbConnectionName].ConnectionString;
            if (connectionProvider.Contains("EntityClient"))
            {
                int ldStartPos = connectionString.ToUpper().IndexOf("DATA SOURCE=");
                int ldEndPos = connectionString.ToUpper().IndexOf(";APP=");
                int ldLength = 0;
                if (ldEndPos > ldStartPos)
                {
                    ldLength = ldEndPos - ldStartPos;
                }
                connectionString = connectionString.Substring(ldStartPos, ldLength);
            }
            string dBConnString = connectionString.ToUpper().Replace(this._lmT2ServerName, this._lmT2ServerIPV4Addr);
            int ldUserIDPos = dBConnString.ToUpper().IndexOf(";", dBConnString.ToUpper().IndexOf("USER ID="));
            bool ldAppendPassword = false;
            if (ldUserIDPos < 1)
            {
                ldAppendPassword = true;
                ldUserIDPos = 1;
            }
            if (ldAppendPassword)
            {
                this._dBconnectionString = dBConnString + this._lmPassword;
            }
            else
            {
                this._dBconnectionString = dBConnString.Insert(ldUserIDPos, this._lmPassword);
            }
        }

        public void ClearPingException()
        {
            this._lmPingException = null;
        }

        private void InitReg()
        {
            this.InitRegistry("Software", "T2Designs");
            this.InitRegistry(@"Software\T2Designs", "T2DSNetConfig");
            this.InitRegistry(@"Software\T2Designs\T2DSNetConfig", this._dbConnectionName);
        }

        private void InitRegistry(string ParentKey, string ChildKey)
        {
            string ldChild = ParentKey + @"\" + ChildKey;
            RegistryKey ldRegKey1 = Registry.CurrentUser.OpenSubKey(ParentKey, true);
            if ((ldRegKey1 != null) && (Registry.CurrentUser.OpenSubKey(ldChild, true) == null))
            {
                ldRegKey1.CreateSubKey(ChildKey);
            }
        }

        private string LoadIPRegData(string ParentKey, string RegKey)
        {
            string ldIPAddress = "127.0.0.1";
            RegistryKey ldRegKey1 = Registry.CurrentUser.OpenSubKey(ParentKey, true);
            if (ldRegKey1.GetValueNames().Contains<string>(RegKey))
            {
                string ldRegVal = ldRegKey1.GetValue(RegKey).ToString();
                if (ldRegVal.Trim().Length > 0)
                {
                    ldIPAddress = ldRegVal;
                }
            }
            return ldIPAddress;
        }

        public void PingAsyncMain(string ServerName)
        {
            if (ServerName.Length == 0)
            {
                throw new ArgumentException("Ping needs a host or IP Address.");
            }
            string who = ServerName;
            AutoResetEvent waiter = new AutoResetEvent(false);
            Ping pingSender = new Ping();
            pingSender.PingCompleted += new PingCompletedEventHandler(this.PingCompletedCallback);
            string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
            byte[] buffer = Encoding.ASCII.GetBytes(data);
            int timeout = 0x2ee0;
            PingOptions options = new PingOptions(0x40, true);
            pingSender.SendAsync(who, timeout, buffer, options, waiter);
        }

        private void PingCompletedCallback(object sender, PingCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                ((AutoResetEvent)e.UserState).Set();
            }
            if (e.Error != null)
            {
                ((AutoResetEvent)e.UserState).Set();
            }
            PingReply reply = e.Reply;
            this.ProcessReply(reply);
            ((AutoResetEvent)e.UserState).Set();
        }

        public void PingSyncMain(string ServerName)
        {
            try
            {
                Ping pingSender = new Ping();
                PingOptions options = new PingOptions
                {
                    DontFragment = true
                };
                string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
                byte[] buffer = Encoding.ASCII.GetBytes(data);
                int timeout = 120;
                PingReply reply = pingSender.Send(ServerName, timeout, buffer, options);
                if (reply.Status == IPStatus.Success)
                {
                    this._lmT2ServerIPV4Addr = reply.Address.ToString();
                    this.Save2Reg(@"Software\T2Designs\T2DSNetConfig\" + this._dbConnectionName, this.ctIPRegName, reply.Address.ToString());
                    this.Save2Reg(@"Software\T2Designs\T2DSNetConfig\" + this._dbConnectionName, this.ctIPRefreshName, this.ldIPRefresh);
                    this.BuildConnectionString();
                }
            }
            catch (Exception ex)
            {
                this._lmPingException = ex;
            }
        }

        public void ProcessReply(PingReply reply)
        {
            if ((reply != null) && (reply.Status == IPStatus.Success))
            {
                this._lmT2ServerIPV4Addr = reply.Address.ToString();
                this.Save2Reg(@"Software\T2Designs\T2DSNetConfig\" + this._dbConnectionName, this.ctIPRegName, reply.Address.ToString());
                this.Save2Reg(@"Software\T2Designs\T2DSNetConfig\" + this._dbConnectionName, this.ctIPRefreshName, this.ldIPRefresh);
                this.BuildConnectionString();
            }
        }

        private void Save2Reg(string ParentKey, string RegKey, string RegValue)
        {
            RegistryKey ldRegKey1 = Registry.CurrentUser.OpenSubKey(ParentKey, true);
            bool ldSubKeyExist = ldRegKey1.GetValueNames().Contains<string>(RegKey);
            try
            {
                if (ldSubKeyExist)
                {
                    if (ldRegKey1.GetValue(RegKey).ToString() != RegValue)
                    {
                        ldRegKey1.SetValue(RegKey, RegValue);
                    }
                }
                else
                {
                    ldRegKey1.SetValue(RegKey, RegValue);
                }
            }
            finally
            {
                ldRegKey1.SetValue(RegKey, RegValue);
            }
        }

        private void Search()
        {
            string connectionString;
            int ldStartPos;
            int ldEndPos;
            int ldLength;
            try
            {
                if (DateTime.Now > this.RegIPV4AddressRefresh)
                {
                    connectionString = ConfigurationManager.ConnectionStrings[this._dbConnectionName].ConnectionString;
                    ldStartPos = connectionString.ToUpper().IndexOf("DATA SOURCE=") + 12;
                    if (ldStartPos > 0)
                    {
                        ldEndPos = connectionString.IndexOf(@"\", ldStartPos);
                        if (ldEndPos > ldStartPos)
                        {
                            ldLength = ldEndPos - ldStartPos;
                            this._lmT2ServerName = connectionString.Substring(ldStartPos, ldLength);
                        }
                    }
                    this.PingSyncMain(this._lmT2ServerName);
                }
            }
            catch (FormatException)
            {
                connectionString = ConfigurationManager.ConnectionStrings[this._dbConnectionName].ConnectionString;
                ldStartPos = connectionString.ToUpper().IndexOf("DATA SOURCE=") + 12;
                if (ldStartPos > 0)
                {
                    ldEndPos = connectionString.IndexOf(@"\", ldStartPos);
                    if (ldEndPos > ldStartPos)
                    {
                        ldLength = ldEndPos - ldStartPos;
                        this._lmT2ServerName = connectionString.Substring(ldStartPos, ldLength);
                    }
                }
                this.PingSyncMain(this._lmT2ServerName);
            }
        }

        public string dBConnectionName
        {
            get
            {
                return this._dbConnectionName;
            }
        }

        public string dBConnectionString
        {
            get
            {
                return this._dBconnectionString;
            }
        }

        public string IPV4Address
        {
            get
            {
                return this._lmT2ServerIPV4Addr;
            }
        }

        public Exception PingException
        {
            get
            {
                return this._lmPingException;
            }
        }

        public string RegIPV4Address
        {
            get
            {
                string ldreturn = "127.0.0.1";
                string ldIPAddress = this.LoadIPRegData(@"Software\T2Designs\T2DSNetConfig\" + this._dbConnectionName, this.ctIPRegName);
                if (ldIPAddress.Length > 0)
                {
                    ldreturn = ldIPAddress;
                }
                return ldreturn;
            }
        }

        public DateTime RegIPV4AddressRefresh
        {
            get
            {
                DateTime ldreturn = DateTime.Today.AddDays(-1.0);
                string ldIPAddressRefresh = this.LoadIPRegData(@"Software\T2Designs\T2DSNetConfig\" + this._dbConnectionName, this.ctIPRefreshName);
                if (ldIPAddressRefresh.Length > 0)
                {
                    ldreturn = Convert.ToDateTime(ldIPAddressRefresh);
                }
                return ldreturn;
            }
        }

        public string ServerName
        {
            get
            {
                return this._lmT2ServerName;
            }
        }

        public string SetPassword
        {
            set
            {
                this._lmPassword = ";Password=" + value;
            }
        }

    }
}
