﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
using static System.Linq.Expressions.Expression;
using static Lenses.ExpressionHelpers;

namespace Lenses
{
    public static class Assets
    {
        internal static readonly MethodInfo copyMethod =
            typeof(object).GetMethod("MemberwiseClone",
                BindingFlags.NonPublic |
                BindingFlags.Instance);

        internal static readonly Func<object, object> Clone = _cloneFunc();

        private static Func<object, object> _cloneFunc()
        {
            var container = Parameter<object>("object");

            var methodCallExpression = Call(container, copyMethod);
            var lambda = Lambda<Func<object, object>>(methodCallExpression, container);

            return lambda.Compile();
        }

        internal static Expression<Action<object, object>> SetValue(FieldInfo field) =>
            (obj, value) => field.SetValue(obj, value);
    }

    public class CloneProvider : ICloneable
    {
        public static MethodInfo Method { get; } = new CloneProvider()._Method();

        public object Clone() => MemberwiseClone();

        private MethodInfo _Method()
        {
            Expression<Func<object>> clone = () => MemberwiseClone();
            return clone.Body.Cast<MethodCallExpression>().Method;
        }

        private CloneProvider() { }
    }
}
