using System;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;

namespace QC.QMine.QMineInterface;

public static class ObjectCopier
{
	public static object GetCopy(object sourceObject)
	{
		if (sourceObject != null)
		{
			try
			{
				Type type = sourceObject.GetType();
				if (type.IsSerializable)
				{
					AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
					MemoryStream memoryStream = new MemoryStream();
					BinaryFormatter binaryFormatter = new BinaryFormatter();
					binaryFormatter.Serialize(memoryStream, sourceObject);
					memoryStream.Seek(0L, SeekOrigin.Begin);
					object result = binaryFormatter.Deserialize(memoryStream);
					AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
					return result;
				}
				return CopyUsingReflection(sourceObject);
			}
			catch (Exception innerException)
			{
				throw new Exception("Error generating a copy", innerException);
			}
		}
		return null;
	}

	private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
	{
		try
		{
			Assembly assembly = Assembly.Load(args.Name);
			if (assembly != null)
			{
				return assembly;
			}
			return Assembly.GetExecutingAssembly();
		}
		catch
		{
			return Assembly.GetExecutingAssembly();
		}
	}

	public static object CopyUsingReflection(object objObject)
	{
		Type type = objObject.GetType();
		PropertyInfo[] properties = type.GetProperties();
		object obj = type.InvokeMember("", BindingFlags.CreateInstance, null, objObject, null);
		PropertyInfo[] array = properties;
		foreach (PropertyInfo propertyInfo in array)
		{
			if (propertyInfo.PropertyType.IsValueType)
			{
				if (propertyInfo.CanWrite)
				{
					propertyInfo.SetValue(obj, propertyInfo.GetValue(objObject, null), null);
				}
			}
			else
			{
				propertyInfo.SetValue(obj, CopyUsingReflection(propertyInfo.GetValue(objObject, null)), null);
			}
		}
		return obj;
	}
}
