using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.DirectoryServices;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Principal;
using System.Text;
using System.Windows.Forms;
using System.Xml;

namespace QC.QTMSecurity;

public class QSecurity
{
	internal const string QSPR_OPERATORS = "QSPR Operators";

	internal const string QSPR_TECHNICIANS = "QSPR Technicians";

	internal const string QSPR_ENGINEERS = "QSPR Engineers";

	internal const string QTM_TECHNICIANS = "QTM Technicians";

	internal const string QTM_ENGINEERS = "QTM Engineers";

	internal const string BUILTIN_QSPR_POWER_USERS = "\\QSPR Power Users";

	internal const string BUILTIN_QSPR_TECH_USERS = "\\QSPR Tech Users";

	internal const string BUILTIN_QTM_POWER_USERS = "\\QTM Power Users";

	internal const string BUILTIN_QTM_TECH_USERS = "\\QTM Tech Users";

	internal const string SECURITY_CONFIG_FOLDER = "C:\\Qualcomm\\Common\\Security";

	internal const string SECURITY_CONFIG_FILE = "Security.config";

	private static WindowsImpersonationContext impersonationContext;

	private static bool impersonating;

	private static AccessLevel userAccessLevel;

	private static SecurityConfiguration securityConfig;

	public static Action<List<string>> OnUserLoginChanged { get; set; }

	public static AccessLevel UserAccessLevel => userAccessLevel;

	public static bool IsPasswordMode => securityConfig.SecurityMode == SecurityMode.Password;

	public static bool IsSecurityDisabled => securityConfig.DisableAll;

	public static bool Impersonating => impersonating;

	public static bool IsOperator
	{
		get
		{
			if (userAccessLevel >= AccessLevel.Operator)
			{
				return true;
			}
			return false;
		}
	}

	public static bool IsEngineer
	{
		get
		{
			if (userAccessLevel >= AccessLevel.Engineer)
			{
				return true;
			}
			return false;
		}
	}

	public static bool IsTechnician
	{
		get
		{
			if (userAccessLevel >= AccessLevel.Technician)
			{
				return true;
			}
			return false;
		}
	}

	public static List<string> TestQGroups { get; set; }

	public static bool LockedQGroup { get; set; }

	public static event UserAccessLevelChangedEventHandler UserAccessLevelChanged;

	static QSecurity()
	{
		impersonationContext = null;
		impersonating = false;
		userAccessLevel = AccessLevel.Operator;
		securityConfig = new SecurityConfiguration();
		AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
		LoadSecurityConfig();
	}

	[DllImport("advapi32.dll", SetLastError = true)]
	private static extern bool LogonUser(string principal, string domain, string password, LogonTypes logonType, LogonProviders logonProvider, out IntPtr token);

	[DllImport("kernel32.dll", SetLastError = true)]
	private static extern bool CloseHandle(IntPtr handle);

	[DllImport("Kernel32.dll")]
	private static extern int GetLastError();

	public static bool Login(string userName, string password, string domain)
	{
		try
		{
			if (impersonating)
			{
				Logout();
			}
			IntPtr token;
			bool flag = LogonUser(userName, domain, password, LogonTypes.Interactive, LogonProviders.Default, out token);
			if (flag)
			{
				ImpersonateIdentity(token);
				if (OnUserLoginChanged != null)
				{
					OnUserLoginChanged(GetAllGroups().ToList());
				}
			}
			return flag;
		}
		catch
		{
		}
		return false;
	}

	public static bool Logout()
	{
		try
		{
			if (impersonationContext != null)
			{
				impersonationContext.Undo();
				SetAccessLevel();
				impersonating = false;
				return true;
			}
			return true;
		}
		catch
		{
		}
		return false;
	}

	public static bool PasswordLogin(string password)
	{
		try
		{
			if (securityConfig.Password == password)
			{
				SetAccessLevel(AccessLevel.Engineer);
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	public static bool PasswordLogout()
	{
		try
		{
			SetAccessLevel(AccessLevel.Operator);
			return true;
		}
		catch
		{
		}
		return false;
	}

	public static bool ChangePassword(string oldPass, string newPass, string confirmPass)
	{
		bool result = false;
		if (IsEngineer && securityConfig.Password == oldPass && newPass == confirmPass)
		{
			securityConfig.Password = newPass;
			SaveSecurityConfig();
			result = true;
		}
		return result;
	}

	public static bool SwitchToPasswordMode(string password, string confirmPass)
	{
		try
		{
			if (IsEngineer && securityConfig.SecurityMode != SecurityMode.Password && password == confirmPass && !string.IsNullOrEmpty(password))
			{
				securityConfig.SecurityMode = SecurityMode.Password;
				securityConfig.Password = password;
				SaveSecurityConfig();
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	public static bool SwitchToWindowsGroupMode()
	{
		try
		{
			if (IsEngineer && securityConfig.SecurityMode == SecurityMode.Password)
			{
				securityConfig.SecurityMode = SecurityMode.WindowsUserGroup;
				SaveSecurityConfig();
				SetAccessLevel();
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	public static bool LoggedInWithPassword()
	{
		if (IsEngineer && securityConfig.SecurityMode == SecurityMode.Password)
		{
			return true;
		}
		return false;
	}

	private static void ImpersonateIdentity(IntPtr logonToken)
	{
		try
		{
			WindowsIdentity windowsIdentity = new WindowsIdentity(logonToken, "NTLM", WindowsAccountType.Normal, isAuthenticated: true);
			impersonationContext = windowsIdentity.Impersonate();
			impersonating = true;
			SetAccessLevel();
		}
		catch
		{
		}
	}

	private static string GetConfigFilePath()
	{
		if (!Directory.Exists("C:\\Qualcomm\\Common\\Security"))
		{
			Directory.CreateDirectory("C:\\Qualcomm\\Common\\Security");
		}
		return Path.Combine("C:\\Qualcomm\\Common\\Security", "Security.config");
	}

	private static void LoadSecurityConfig()
	{
		string configFilePath = GetConfigFilePath();
		if (!File.Exists(configFilePath))
		{
			return;
		}
		FileStream fileStream = new FileStream(configFilePath, FileMode.Open);
		try
		{
			BinaryFormatter binaryFormatter = new BinaryFormatter();
			securityConfig = (SecurityConfiguration)binaryFormatter.Deserialize(fileStream);
		}
		catch (Exception ex)
		{
			securityConfig = new SecurityConfiguration();
			securityConfig.SecurityMode = SecurityMode.WindowsUserGroup;
			Console.WriteLine("Failed to read security configuration. " + ex.Message);
		}
		finally
		{
			fileStream.Close();
		}
	}

	public static void SaveSecuritySettings()
	{
		if (securityConfig.SecurityMode == SecurityMode.Password)
		{
			SaveSecurityConfig();
		}
	}

	private static void SaveSecurityConfig()
	{
		string configFilePath = GetConfigFilePath();
		FileStream fileStream = new FileStream(configFilePath, FileMode.Create);
		try
		{
			BinaryFormatter binaryFormatter = new BinaryFormatter();
			binaryFormatter.Serialize(fileStream, securityConfig);
		}
		catch (Exception ex)
		{
			Console.WriteLine("Failed to create security configuration. " + ex.Message);
			throw;
		}
		finally
		{
			fileStream.Close();
		}
	}

	public static void EnableSecurity(bool enable)
	{
		securityConfig.DisableAll = !enable;
		SaveSecurityConfig();
		SetAccessLevel();
	}

	public static void SetAccessLevel()
	{
		try
		{
			if (securityConfig.DisableAll)
			{
				SetAccessLevel(AccessLevel.Engineer);
			}
			else if (securityConfig.SecurityMode == SecurityMode.Password)
			{
				SetAccessLevel(AccessLevel.Operator);
			}
			else
			{
				AssignAccessUsingNetworkOrGroup();
			}
		}
		catch (Exception ex)
		{
			Console.WriteLine(ex.Message);
		}
	}

	public static void SetAccessLevel(AccessLevel assignedAccessLevel)
	{
		try
		{
			if (userAccessLevel != assignedAccessLevel)
			{
				userAccessLevel = assignedAccessLevel;
				OnUserAccessLevelChanged();
			}
		}
		catch (Exception ex)
		{
			Console.WriteLine(ex.Message);
		}
	}

	private static void AssignAccessUsingNetworkOrGroup()
	{
		WindowsPrincipal windowsPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
		string text = windowsPrincipal.Identity.Name.Split('\\')[0];
		AccessLevel accessLevel = (windowsPrincipal.IsInRole(text + "\\QSPR Engineers") ? AccessLevel.Engineer : (windowsPrincipal.IsInRole(text + "\\QTM Engineers") ? AccessLevel.Engineer : ((!windowsPrincipal.IsInRole("NA\\QTM Engineers") && !windowsPrincipal.IsInRole("NA\\QSPR Engineers")) ? (windowsPrincipal.IsInRole(SystemInformation.ComputerName + "\\QSPR Power Users") ? AccessLevel.Engineer : (windowsPrincipal.IsInRole(SystemInformation.ComputerName + "\\QTM Power Users") ? AccessLevel.Engineer : (windowsPrincipal.IsInRole(text + "\\QSPR Technicians") ? AccessLevel.Technician : (windowsPrincipal.IsInRole(text + "\\QTM Technicians") ? AccessLevel.Technician : ((windowsPrincipal.IsInRole("NA\\QTM Technicians") || windowsPrincipal.IsInRole("NA\\QSPR Technicians")) ? AccessLevel.Technician : (windowsPrincipal.IsInRole(SystemInformation.ComputerName + "\\QSPR Tech Users") ? AccessLevel.Technician : (windowsPrincipal.IsInRole(SystemInformation.ComputerName + "\\QTM Tech Users") ? AccessLevel.Technician : AccessLevel.Operator))))))) : AccessLevel.Engineer)));
		if (userAccessLevel != accessLevel)
		{
			userAccessLevel = accessLevel;
			OnUserAccessLevelChanged();
		}
	}

	private static void OnUserAccessLevelChanged()
	{
		try
		{
			if (QSecurity.UserAccessLevelChanged != null)
			{
				QSecurity.UserAccessLevelChanged("QSecurity", new UserAccessLevelChangedEventArgs(userAccessLevel));
			}
		}
		catch
		{
		}
	}

	public static bool InGroup(string grp)
	{
		WindowsPrincipal windowsPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
		string text = windowsPrincipal.Identity.Name.Split('\\')[0];
		if (windowsPrincipal.IsInRole("NA\\" + grp))
		{
			return true;
		}
		if (windowsPrincipal.IsInRole(text + "\\" + grp))
		{
			return true;
		}
		return false;
	}

	public static bool ValidateUserInGroup(QGroupsCollection groups)
	{
		WindowsPrincipal windowsPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
		AccessLevel accessLevel = userAccessLevel;
		if (groups.Count > 0)
		{
			string text = windowsPrincipal.Identity.Name.Split('\\')[0];
			accessLevel = AccessLevel.Operator;
			foreach (object group in groups)
			{
				if (windowsPrincipal.IsInRole("NA\\" + group))
				{
					accessLevel = AccessLevel.Engineer;
				}
				if (windowsPrincipal.IsInRole(text + "\\" + group))
				{
					accessLevel = AccessLevel.Engineer;
				}
			}
		}
		if (userAccessLevel != accessLevel)
		{
			userAccessLevel = accessLevel;
			OnUserAccessLevelChanged();
		}
		return accessLevel == AccessLevel.Engineer;
	}

	private static List<string> GetCurrentUserGroups()
	{
		List<string> list = new List<string>();
		try
		{
			string text = null;
			WindowsIdentity current = WindowsIdentity.GetCurrent();
			text = current.Name.ToString().ToLower();
			int startIndex = text.IndexOf("\\") + 1;
			text = text.Substring(startIndex);
			GetGroupsForUsername(list, text);
		}
		catch (Exception)
		{
		}
		return list;
	}

	private static void GetGroupsForUsername(List<string> groupNames, string username)
	{
		string text = Convert.ToBase64String(Encoding.UTF8.GetBytes("ctdscomp@ldap:$Mecaland32"));
		string uriString = "https://cis6dev.qualcomm.com:9402/xml/Enterprise/Solutions/PeopleDS/Public/PDS/getEmployeeGroups?userid=" + username;
		HttpWebRequest httpWebRequest = WebRequest.Create(new Uri(uriString)) as HttpWebRequest;
		httpWebRequest.CookieContainer = new CookieContainer();
		httpWebRequest.Method = "GET";
		httpWebRequest.AllowAutoRedirect = false;
		httpWebRequest.Headers.Add("Authorization", "Basic " + text);
		HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
		StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream());
		string xml = streamReader.ReadToEnd();
		XmlDocument xmlDocument = new XmlDocument();
		xmlDocument.LoadXml(xml);
		XmlNodeList elementsByTagName = xmlDocument.GetElementsByTagName("ns1:cn");
		XmlNodeList elementsByTagName2 = xmlDocument.GetElementsByTagName("ns1:qcGroupType");
		for (int i = 0; i < elementsByTagName2.Count; i++)
		{
			if (elementsByTagName2[i].InnerText == "qgroup" || elementsByTagName2[i].InnerText == "mail_list")
			{
				groupNames.Add(elementsByTagName[i].InnerText);
			}
		}
	}

	protected static HttpWebRequest CreateRequest(string url)
	{
		return WebRequest.Create(new Uri(url)) as HttpWebRequest;
	}

	private static List<string> AllGroups()
	{
		List<string> currentUserGroups = GetCurrentUserGroups();
		if (currentUserGroups.Count > 0)
		{
			return currentUserGroups;
		}
		try
		{
			WindowsIdentity current = WindowsIdentity.GetCurrent();
			string text = current.Name.ToString();
			text = text.ToLower();
			int startIndex = text.IndexOf("\\") + 1;
			text = text.Substring(startIndex);
			string filter = string.Format("(&(ObjectClass={0})(sAMAccountName={1}))", "person", text);
			string text2 = "gc.qualcomm.com:3268";
			string[] value = new string[1] { "fullname" };
			ArrayList arrayList = new ArrayList();
			DirectoryEntry searchRoot = new DirectoryEntry("LDAP://" + text2, null, null, AuthenticationTypes.Secure);
			DirectorySearcher directorySearcher = new DirectorySearcher(searchRoot);
			directorySearcher.SearchScope = SearchScope.Subtree;
			directorySearcher.ReferralChasing = ReferralChasingOption.All;
			directorySearcher.PropertiesToLoad.AddRange(value);
			directorySearcher.Filter = filter;
			SearchResult searchResult = directorySearcher.FindOne();
			searchResult.GetDirectoryEntry();
			if (searchResult != null)
			{
				DirectoryEntry directoryEntry = new DirectoryEntry(searchResult.Path);
				object obj = directoryEntry.Invoke("Groups");
				foreach (object item in (IEnumerable)obj)
				{
					DirectoryEntry directoryEntry2 = new DirectoryEntry(item);
					arrayList.Add(directoryEntry2.Name);
					currentUserGroups.Add(directoryEntry2.Name.Replace("CN=", ""));
				}
			}
		}
		catch (Exception)
		{
		}
		return currentUserGroups;
	}

	public static BindingList<string> GetAllGroups()
	{
		return new BindingList<string>(AllGroups());
	}
}
