using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Interception.InterceptionBehaviors;
using Unity.Interception.PolicyInjection.Pipeline;

namespace VCommon.Ioc
{
    internal class InterceptionBehaviorAdapter<TInterceptor> : IInterceptionBehavior where TInterceptor : IInterceptor
    {
        private readonly IInterceptor _interceptor;

        public InterceptionBehaviorAdapter(TInterceptor interceptor)
        {
            _interceptor = interceptor;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            var svcClass = input.Target.GetType();
            var svcMethod = input.MethodBase;
            IReadOnlyDictionary<string, object> paramDic = Enumerable.Range(0, input.Arguments.Count).ToDictionary(p => input.Arguments.ParameterName(p), p => input.Arguments[p]);

            _interceptor.BeforeInvoke(svcClass, svcMethod, paramDic);

            var result = getNext()(input, getNext);

            _interceptor.AfterInvoke(svcClass, svcMethod, paramDic, result.ReturnValue, result.Exception);

            return result;
        }

        public IEnumerable<Type> GetRequiredInterfaces() => Array.Empty<Type>();

        public bool WillExecute => true;
    }
}
