using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Installables.All;
using Microsoft.Win32;
using Yaulw.Assembly;
using System.IO;
using Yaulw.Xml;

namespace Installables.Setup.PlutoServerMSLService
{
    public class InstallComponent : IInstallComponent , ISetup
    {
        #region Private Helpers

        public const string BRIDGE_SERVICE_TITLE = Common_MediLytec.MediLytecPoundDef.BRIDGE_SERVICE_TITLE;
        public const string BRIDGE_SERVICE_ASSEMBLY = Common_MediLytec.MediLytecPoundDef.BRIDGE_SERVICE_ASSEMBLY;
        public const string BRIDGE_SERVICE_NAME = Common_MediLytec.MediLytecPoundDef.BRIDGE_SERVICE_NAME;

        /// <summary>
        /// Write Service Configuration to the ImagePath for the Service
        /// </summary>
        /// <returns></returns>
        public static bool WriteServiceConfigurationToServiceInRegistry(InstallConfig config)
        {
            try
            {
                using (RegistryKey service = Registry.LocalMachine.OpenSubKey("System\\CurrentControlSet\\services\\" + BRIDGE_SERVICE_TITLE, true))
                {
                    // # Determine Image Path Parameter
                    string ImagePathParameter = "";
                    switch (config)
                    {
                        case InstallConfig.LytecMD:
                            ImagePathParameter = " /Lytec";
                            break;

                        case InstallConfig.MedisoftClinical:
                            ImagePathParameter = " /Medisoft";
                            break;
                    }

                    // # Set Image Path Parameter
                    string serviceAssembly = "\"" + AssemblyW.SpecializedAssemblyInfo.GetAssemblyPath(AssemblyW.AssemblyST.Executing) + "\\" + BRIDGE_SERVICE_ASSEMBLY + "\"";
                    service.SetValue("ImagePath", serviceAssembly + ImagePathParameter);
                    return true;
                }
            }
            catch (Exception) { /* ignore */ }
            return false;
        }

        #endregion

        #region IInstallComponent Members

        public ComponentConfig.Component GetComponent()
        {
            return Common.EmbeddedConfig.SetupComponents.GetComponent("BridgeService");
        }

        public bool BEFORE_INSTALLING_COMPONENT()
        {
            // Stop Service BRIDGE_SERVICE_NAME
            if (!Common.StopService(BRIDGE_SERVICE_NAME))
            {
                Common.Log.Error(String.Format("Couldn't stop the {0} Service.", BRIDGE_SERVICE_NAME));
                return false;
            }

            // Read the Service Configuration from the Registry
            InstallConfig config = Common_MediLytec.RetrieveInstallConfigFromRegistry();
            if (config == InstallConfig.LytecMD)
            {
                bool bSuccess = false;
                string result = Common.RunCmdLine("netsh firewall set portopening tcp 5000 BridgeService_LytecBridgeIn ENABLE ALL");
                bSuccess = result.Contains("successfully") || result.Contains("Ok.") || result.Contains("The service has not been started");
                if (bSuccess)
                {
                    result = Common.RunCmdLine("netsh firewall set portopening tcp 5001 BridgeService_LytecMirthOut ENABLE ALL");
                    bSuccess = result.Contains("successfully") || result.Contains("Ok.") || result.Contains("The service has not been started");                    
                }
                if (bSuccess)
                {
                    return true;
                }
                else
                {
                    Common.Log.Error(String.Format("Opening up ports for Lytec '{0}' failed", BRIDGE_SERVICE_NAME));
                    return false;
                }
            }
            else if (config == InstallConfig.MedisoftClinical)
            {
                bool bSuccess = false;
                string result = Common.RunCmdLine("netsh firewall set portopening tcp 7000 BridgeService_MedisoftBridgeIn ENABLE ALL");
                bSuccess = result.Contains("successfully") || result.Contains("Ok.") || result.Contains("The service has not been started");
                if (bSuccess)
                {
                    result = Common.RunCmdLine("netsh firewall set portopening tcp 7001 BridgeService_MedisoftMirthOut ENABLE ALL");
                    bSuccess = result.Contains("successfully") || result.Contains("Ok.") || result.Contains("The service has not been started");
                }
                if (bSuccess)
                {
                    return true;
                }
                else
                {
                    Common.Log.Error(String.Format("Opening up ports for Medisoft '{0}' failed", BRIDGE_SERVICE_NAME));
                    return false;
                }
            }            
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool INSTALL_COMPONENT()
        {
            // Uninstall Bridge Service, if it exists, and re-install
            if (Common.ServiceExists(BRIDGE_SERVICE_NAME))
                UNINSTALL_COMPONENT();            

            string installUtil = Common.GetNetFrameworkUtilFileNameNPathFile("installutil.exe");
            string serviceAssembly = AssemblyW.SpecializedAssemblyInfo.GetAssemblyPath(AssemblyW.AssemblyST.Entry) + "\\" + BRIDGE_SERVICE_ASSEMBLY;
            if (!String.IsNullOrEmpty(installUtil))
            {
                Common.StopService(BRIDGE_SERVICE_NAME);
                string result = Common.RunCmdLine(installUtil + " \"" + serviceAssembly + "\"");
                bool bSuccess = !result.Contains("failed");
                if (bSuccess)
                {                    
                    // Write the Service Configuration to the Registry
                    InstallConfig config = Common_MediLytec.RetrieveInstallConfigFromRegistry();
                    bSuccess = WriteServiceConfigurationToServiceInRegistry(config);
                }
                if (!bSuccess)
                {
                    Common.Log.Error(String.Format("Errors Occured installing {0}.", BRIDGE_SERVICE_NAME));
                }                                
                return bSuccess;
            }
            return false;
        }

        public bool AFTER_INSTALLING_COMPONENT()
        {            
            // Make sure service exists
            if (!Common.ServiceExists(BRIDGE_SERVICE_NAME))
            {
                Common.Log.Error(String.Format("Service {0} does Not Exist. Install Failed", BRIDGE_SERVICE_NAME));
                return false;
            }

            // Make sure Service is stopped
            Common.StopService(BRIDGE_SERVICE_NAME);
            return true;            
        }

        public bool SUPPORTS_UNINSTALL()
        {
            return false;
        }

        public bool BEFORE_UNINSTALLING_COMPONENT()
        {
            // Stop Service BRIDGE_SERVICE_NAME
            if (!Common.StopService(BRIDGE_SERVICE_NAME))
            {
                Common.Log.Error(String.Format("Couldn't stop the {0} Service.", BRIDGE_SERVICE_NAME));
                return false;
            }
            return true;            
        }

        public bool UNINSTALL_COMPONENT()
        {
            if (Common.ServiceExists(BRIDGE_SERVICE_NAME))
            {
                Common.StopService(BRIDGE_SERVICE_NAME);
                string installUtil = Common.GetNetFrameworkUtilFileNameNPathFile("installutil.exe");
                string serviceAssembly = AssemblyW.SpecializedAssemblyInfo.GetAssemblyPath(AssemblyW.AssemblyST.Entry) + "\\" + BRIDGE_SERVICE_ASSEMBLY;
                if (!String.IsNullOrEmpty(installUtil))
                {
                    string result = Common.RunCmdLine(installUtil + " /u \"" + serviceAssembly + "\"");
                    bool bSuccess = !result.Contains("failed");
                    if(!bSuccess)
                        Common.Log.Error(String.Format("Errors Occured uninstalling {0}.", BRIDGE_SERVICE_NAME));
                    return bSuccess;
                }
            }
            return false;            
        }

        public bool AFTER_UNINSTALLING_COMPONENT()
        {
            if (Common.ServiceExists(BRIDGE_SERVICE_NAME))
            {
                Common.Log.Error(String.Format("Service {0} Still Exists. Uninstall Failed", BRIDGE_SERVICE_NAME));
                return false;
            }
            return true;
        }

        #endregion

        #region ISetup Members

        public void ComponentLoaded(ref SetupEvents subscribeToDesiredEvents)
        {
            subscribeToDesiredEvents.Before_Install += new SetupEvents.SetupEvent(subscribeToDesiredEvents_Before_Install);
            subscribeToDesiredEvents.After_Install += new SetupEvents.SetupEvent(subscribeToDesiredEvents_After_Install);
            subscribeToDesiredEvents.Ending_Setup += new SetupEvents.SetupEvent(subscribeToDesiredEvents_Ending_Setup);
        }

        void subscribeToDesiredEvents_Ending_Setup()
        {
            if (Common.ServiceExists(BRIDGE_SERVICE_NAME))
            {
                string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\McKesson\\Bridge\\BridgeConfig.xml";
                if (File.Exists(path))
                {
                    XSerializer serialize = new XSerializer();
                    // * Go over this * 
                    //XMLConfig config = serialize.ReadFromFile<XMLConfig>(path);
                    //if (config != null)
                    //{
                    //    // Read the Service Configuration from the Registry
                    //    InstallConfig sconfig = Common_MediLytec.RetrieveInstallConfigFromRegistry();
                    //    if (sconfig == InstallConfig.LytecMD && !String.IsNullOrEmpty(config.DefaultMapping.Lytec))
                    //        Common.StartService(BRIDGE_SERVICE_NAME);
                    //    else if(sconfig == InstallConfig.MedisoftClinical && !String.IsNullOrEmpty(config.DefaultMapping.Medisoft))
                    //        Common.StartService(BRIDGE_SERVICE_NAME);
                    //}
                }
            }
        }

        void subscribeToDesiredEvents_Before_Install()
        {
            
        }

        void subscribeToDesiredEvents_After_Install()
        {
            
        }

        #endregion
    }
}
