using System.Reflection;
using AyCode.Core.Extensions;

namespace AyCode.Services.SignalRs;

public static class TrackingItemHelpers
{
    public static T JsonClone<T>(T source) => source.ToJson().JsonTo<T>()!;

    public static T ReflectionClone<T>(T source)
    {
        var type = source!.GetType();

        if (type.IsPrimitive || typeof(string) == type)
            return source;

        if (type.IsArray)
        {
            var elementType = Type.GetType(type.FullName!.Replace("[]", string.Empty))!;
            var array = (source as Array)!;
            var cloned = Array.CreateInstance(elementType, array.Length);

            for (var i = 0; i < array.Length; i++)
                cloned.SetValue(ReflectionClone(array.GetValue(i)), i);

            return (T)Convert.ChangeType(cloned, type);
        }

        var clone = Activator.CreateInstance(type);

        while (type != null && type != typeof(object))
        {
            foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                var fieldValue = field.GetValue(source);
                if (fieldValue == null) continue;

                field.SetValue(clone, ReflectionClone(fieldValue));
            }

            type = type.BaseType;
        }

        return (T)clone!;
    }
}