using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.Diagnostics;
using System.DirectoryServices;
using System.IO;
using System.Text;
using Microsoft.Win32;

namespace QSPRCustomAction;

[RunInstaller(true)]
public class CustomInstall : Installer
{
	private const string SUBKEY = "Path";

	private const string QTM_POWER_USERS = "QSPR Power Users";

	private const string QTM_GROUP_DESCRIPTION = "QSPR Power Users have Engineer Privileges to run QSPR";

	private const string QTM_TECH_USERS = "QSPR Tech Users";

	private const string QTM_TECH_GROUP_DESCRIPTION = "QSPR Tech Users have Technician Privileges to run QSPR";

	public override void Install(IDictionary stateSaver)
	{
		base.Install(stateSaver);
		WriteLogMsg("\n\nBegin Install");
		WriteLogMsg(string.Concat("Computer Name: ", Environment.MachineName, "\nOS: ", Environment.OSVersion, "\nVersion: ", Environment.Version, "\nUserName: ", Environment.UserName));
		string text = "";
		foreach (DictionaryEntry parameter in base.Context.Parameters)
		{
			if (parameter.Key.ToString().Equals("dst"))
			{
				text = parameter.Value.ToString();
				break;
			}
		}
		stateSaver.Add("dst", text);
		foreach (DictionaryEntry parameter2 in base.Context.Parameters)
		{
			string text2 = parameter2.Key.ToString() + "=" + parameter2.Value.ToString();
			WriteLogMsg(text2);
		}
		DeleteMFCfiles(text);
		QSPR3_Install(text);
	}

	public override void Uninstall(IDictionary savedState)
	{
		base.Uninstall(savedState);
		WriteLogMsg("\n\nBegin Uninstall");
		string dst = "";
		foreach (DictionaryEntry item in savedState)
		{
			if (item.Key.ToString().Equals("dst"))
			{
				dst = item.Value.ToString();
				break;
			}
		}
		QSPR3_Uninstall(dst);
	}

	public override void Commit(IDictionary stateSaver)
	{
		base.Commit(stateSaver);
	}

	public void RegisterXTTFileType(string dst)
	{
		Registry.ClassesRoot.DeleteSubKeyTree(".xtt");
		Registry.ClassesRoot.Close();
		RegistryKey registryKey = Registry.ClassesRoot.CreateSubKey(".xtt");
		registryKey.CreateSubKey("QSPR XTT Test Tree");
		registryKey.SetValue("", "QSPR XTT Test Tree");
		Registry.ClassesRoot.Close();
		Registry.ClassesRoot.DeleteSubKeyTree("QSPR Test Tree");
		Registry.ClassesRoot.Close();
		RegistryKey registryKey2 = Registry.ClassesRoot.CreateSubKey("QSPR XTT Test Tree");
		RegistryKey registryKey3 = registryKey2.CreateSubKey("shell").CreateSubKey("open").CreateSubKey("command");
		registryKey3.SetValue("", "\"" + dst + "bin\\QSPR.exe\" \"%1\"");
		RegistryKey registryKey4 = registryKey2.CreateSubKey("DefaultIcon");
		registryKey4.SetValue("", dst + "bin\\tree.ico");
		Registry.ClassesRoot.Close();
	}

	public override void Rollback(IDictionary savedState)
	{
		base.Rollback(savedState);
		foreach (DictionaryEntry item in savedState)
		{
			if (item.Key.ToString().Equals("dst"))
			{
				item.Value.ToString();
				break;
			}
		}
	}

	public void BackupWorkspaceConfig()
	{
		string text = Path.GetPathRoot(Environment.SystemDirectory) + "Qualcomm\\QSPR\\QSPRConfigurations\\Workspace.config";
		if (File.Exists(text))
		{
			try
			{
				File.Copy(text, text + ".old", overwrite: true);
			}
			catch
			{
			}
		}
	}

	public void QSPR3_Install(string dst)
	{
		_ = dst + "bin\\QSPR.exe";
		WriteLogMsg("In QSPR3_Install");
		CheckDotNetFramework();
		RegisterAutomationInterface(dst, "QSPRAutomationInterface");
		RegisterAutomationInterface(dst, "QSPRSchedulerWrapper");
		SetPathVariable(dst);
		AddQSPRPowerUsersGroup();
		AddQSPRTechUsersGroup();
		AddAdminUsersToQSPRPowerUsersGroup();
		LogInstallProperties();
		UpdateQSPRConfigFiles();
	}

	private void LogInstallProperties()
	{
		StringBuilder stringBuilder = new StringBuilder();
		if (base.Context.Parameters.Count > 0)
		{
			foreach (string key in base.Context.Parameters.Keys)
			{
				stringBuilder.AppendLine($"Name={key}; Value= {base.Context.Parameters[key]}");
			}
		}
		WriteLogMsg("Properties passed to Custom Actions:\n" + stringBuilder.ToString());
	}

	private void UpdateQSPRConfigFiles()
	{
		WriteLogMsg("\n\nUpdating QSPR config files");
		try
		{
			string text = base.Context.Parameters["USERSELECTION"].ToString();
			string text2 = base.Context.Parameters["dst"].ToString();
			string text3 = Path.GetPathRoot(Environment.SystemDirectory) + "Qualcomm\\QSPR\\QSPRConfigurations\\Workspace.config";
			string text4 = Path.GetPathRoot(Environment.SystemDirectory) + "Qualcomm\\QSPR\\QSPRConfigurations\\Workspace_NEW.config";
			string text5 = text2 + "bin\\Feature.config";
			string text6 = text2 + "bin\\Feature_NEW.config";
			WriteLogMsg("\n\nUSERSELECTION=" + text);
			if (text != "2")
			{
				WriteLogMsg("\n\nReplacing workspace config with new file");
				if (File.Exists(text4))
				{
					try
					{
						WriteLogMsg("\n\nCopying new workspace config");
						if (File.Exists(text3))
						{
							File.SetAttributes(text3, File.GetAttributes(text3) & ~FileAttributes.ReadOnly);
						}
						File.Copy(text4, text3, overwrite: true);
						WriteLogMsg("\n\nFile successfully copied");
					}
					catch (Exception ex)
					{
						WriteLogMsg("\n\nEXCEPTION copying new workspace config: " + ex.ToString());
					}
				}
				WriteLogMsg("\n\nReplacing feature config with new file");
				if (File.Exists(text6))
				{
					try
					{
						WriteLogMsg("\n\nCopying new feature config");
						if (File.Exists(text5))
						{
							File.SetAttributes(text5, File.GetAttributes(text5) & ~FileAttributes.ReadOnly);
						}
						File.Copy(text6, text5, overwrite: true);
						WriteLogMsg("\n\nFile successfully copied");
					}
					catch (Exception ex2)
					{
						WriteLogMsg("\n\nEXCEPTION copying new feature config: " + ex2.ToString());
					}
				}
			}
		}
		catch (Exception ex3)
		{
			WriteLogMsg("\n\nEXCEPTION updating QSPR config files: " + ex3.ToString());
		}
		WriteLogMsg("\n\nUpdate QSPR config files done");
	}

	public void QSPR3_Uninstall(string dst)
	{
		UnregisterAutomationInterface(dst, "QSPRAutomationInterface");
		UnregisterAutomationInterface(dst, "QSPRSchedulerWrapper");
	}

	private void RegisterAutomationInterface(string dst, string dllNameWithoutExtension)
	{
		try
		{
			WriteLogMsg("Register automation interface");
			ProcessStartInfo processStartInfo = new ProcessStartInfo("C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\regasm");
			processStartInfo.WindowStyle = ProcessWindowStyle.Minimized;
			string text = Path.Combine(Path.Combine(dst, "bin"), dllNameWithoutExtension + ".dll");
			string text2 = Path.Combine(Path.Combine(dst, "bin"), dllNameWithoutExtension + ".tlb");
			processStartInfo.Arguments = $"\"{text}\" /tlb:\"{text2}\" /codebase";
			Process process = Process.Start(processStartInfo);
			process.WaitForExit();
			if (!File.Exists(text2))
			{
				WriteLogMsg("Error registering QSPR automation, tlb was not created: " + text2);
				return;
			}
			WriteLogMsg("Generated tlb file " + text2);
			WriteLogMsg("Registered " + text);
		}
		catch (Exception ex)
		{
			WriteLogMsg($"RegisterAutomationInterface failed, Error: {ex.Message}, InnerException: {ex.InnerException}");
		}
	}

	private void UnregisterAutomationInterface(string dst, string dllNameWithoutExtension)
	{
		try
		{
			WriteLogMsg("UnRegister automation interface");
			ProcessStartInfo processStartInfo = new ProcessStartInfo("C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\regasm");
			processStartInfo.WindowStyle = ProcessWindowStyle.Minimized;
			string text = Path.Combine(Path.Combine(dst, "bin"), dllNameWithoutExtension + ".dll");
			processStartInfo.Arguments = $"/unregister \"{text}\" ";
			Process.Start(processStartInfo);
			WriteLogMsg("UnRegistered " + text);
		}
		catch (Exception ex)
		{
			WriteLogMsg($"UnregisterAutomationInterface, Error: {ex.Message}, InnerException: {ex.InnerException}");
		}
	}

	private void SetPathVariable(string dst)
	{
		try
		{
			WriteLogMsg("Setting Path variable");
			string environmentVariable = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
			if (environmentVariable.ToUpper().IndexOf(Path.Combine(dst, "bin").ToUpper().Trim()) == -1)
			{
				Environment.SetEnvironmentVariable("Path", Path.Combine(dst, "bin") + ";" + environmentVariable, EnvironmentVariableTarget.Machine);
				WriteLogMsg("Adding QSPR directory");
			}
		}
		catch (Exception ex)
		{
			WriteLogMsg($"Failed to set path variable, Error: {ex.Message}, InnerException: {ex.InnerException}");
		}
	}

	private void AddAdminUsersToQSPRPowerUsersGroup()
	{
		try
		{
			WriteLogMsg("Getting admin users to add to QSPR Power Users group");
			DirectoryEntry directoryEntry = new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer");
			WriteLogMsg("Found QSPR Power Users Group");
			DirectoryEntry directoryEntry2 = directoryEntry.Children.Find("QSPR Power Users", "group");
			if (directoryEntry2 != null)
			{
				using DirectoryEntry directoryEntry3 = new DirectoryEntry("WinNT://./Administrators,group");
				foreach (object item in (IEnumerable)directoryEntry3.Invoke("Members"))
				{
					using DirectoryEntry directoryEntry4 = new DirectoryEntry(item);
					try
					{
						directoryEntry2.Invoke("Add", directoryEntry4.Path.ToString());
						WriteLogMsg("Added user " + directoryEntry4.Path.ToString());
					}
					catch (Exception ex)
					{
						WriteLogMsg(string.Format("Failed to add user,{2} Error: {0}, InnerException: {1}", ex.Message, ex.InnerException, directoryEntry4.Path.ToString()));
					}
				}
			}
			WriteLogMsg("Done adding admin users to QSPR Power Users group");
		}
		catch (Exception ex2)
		{
			WriteLogMsg($"Failed on adding admin user to group, Error: {ex2.Message}, InnerException: {ex2.InnerException}");
		}
	}

	private void AddQSPRTechUsersGroup()
	{
		try
		{
			WriteLogMsg("Start to create QSPR Tech Users group");
			WriteLogMsg("Getting WinNT directory");
			DirectoryEntry directoryEntry = new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer");
			WriteLogMsg("Setup QSPR Tech Users group");
			DirectoryEntry directoryEntry2 = directoryEntry.Children.Add("QSPR Tech Users", "group");
			WriteLogMsg("setup QSPR Tech Users group's description");
			directoryEntry2.Invoke("Put", "Description", "QSPR Tech Users have Technician Privileges to run QSPR");
			WriteLogMsg("Adding QSPR Tech Users group");
			directoryEntry2.CommitChanges();
			WriteLogMsg("Done creating QSPR Tech Users group");
		}
		catch (Exception ex)
		{
			WriteLogMsg($"Failed to create QSPR Tech Users group, Error: {ex.Message}, InnerException: {ex.InnerException}");
		}
	}

	private void AddQSPRPowerUsersGroup()
	{
		try
		{
			WriteLogMsg("Start to create QSPR Power Users group");
			WriteLogMsg("Getting WinNT directory");
			DirectoryEntry directoryEntry = new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer");
			WriteLogMsg("setup QSPR Power Users group");
			DirectoryEntry directoryEntry2 = directoryEntry.Children.Add("QSPR Power Users", "group");
			WriteLogMsg("setup group description");
			directoryEntry2.Invoke("Put", "Description", "QSPR Power Users have Engineer Privileges to run QSPR");
			WriteLogMsg("Adding QSPR Power Users group");
			directoryEntry2.CommitChanges();
			WriteLogMsg("Done creating QSPR Power Users group");
		}
		catch (Exception ex)
		{
			WriteLogMsg($"Failed to create QSPR Power Users group, Error: {ex.Message}, InnerException: {ex.InnerException}");
		}
	}

	private void CheckDotNetFramework()
	{
		try
		{
			RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Client");
			WriteLogMsg("open subkey to read .net framework");
			string text = registryKey.GetValue("Version").ToString();
			WriteLogMsg(".net framework version is " + text);
		}
		catch (Exception ex)
		{
			WriteLogMsg($"Failed to find .net framework 4.0 Client installation, Error: {ex.Message}, InnerException: {ex.InnerException}");
			throw new Exception(".NET Framework 4.0 Client Profile is REQUIRED to run the application.  Please install .NET Framework 4.0 CP from http://www.microsoft.com/en-us/download/details.aspx?id=24872. ");
		}
	}

	private void WriteLogMsg(string text)
	{
		try
		{
			string path = "C:\\Log";
			if (!Directory.Exists(path))
			{
				Directory.CreateDirectory(path);
			}
			using StreamWriter streamWriter = new StreamWriter("C:\\Log\\QSPR_Ext_Installer.log", append: true);
			streamWriter.WriteLine($"{DateTime.Now} - " + text);
		}
		catch (Exception)
		{
		}
	}

	public void DeleteMFCfiles(string dst)
	{
		string path = dst + "mfc71.dll";
		string path2 = dst + "mfc71u.dll";
		string path3 = dst + "msvcp71.dll";
		string path4 = dst + "msvcr71.dll";
		string path5 = dst + "QSPR.lnk";
		try
		{
			File.Delete(path);
			File.Delete(path2);
			File.Delete(path3);
			File.Delete(path4);
			File.Delete(path5);
		}
		catch (Exception)
		{
		}
	}

	private void InitializeComponent()
	{
	}
}
