using Microsoft.Azure.WebJobs.Description;
using Microsoft.Azure.WebJobs.Host.Bindings;
using Microsoft.Azure.WebJobs.Host.Config;
using Microsoft.Azure.WebJobs.Host.Protocols;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace DotNetDevOps.Extensions.AzureEventGrid.EventManagerApi.Authorization
{
    [Binding]
    [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.ReturnValue)]
    public class InjectAttribute : Attribute
    {

    }

    public class InjectBindingProvider : IBindingProvider
    {



        public Task<IBinding> TryCreateAsync(BindingProviderContext context)
        {


            return Task.FromResult(new InjectBinding { Type = context.Parameter.ParameterType } as IBinding);
        }
    }
    public class InjectBinding : IBinding
    {
        public Type Type { get; set; }

        public bool FromAttribute => throw new NotImplementedException();

        public Task<IValueProvider> BindAsync(object value, ValueBindingContext context)
        {
            throw new NotImplementedException();
        }

        public Task<IValueProvider> BindAsync(BindingContext context)
        {
            return Task.FromResult(new InjectValue
            {
                Type = Type,
                Context = context
            } as IValueProvider);
        }

        public ParameterDescriptor ToParameterDescriptor()
        {
            return new ParameterDescriptor
            {
                Name = "test",
                Type = "test",
                DisplayHints = new ParameterDisplayHints
                {
                    DefaultValue = "world",
                    Description = "test",
                    Prompt = "helo"
                },
                ExtendedProperties = new Dictionary<string, Newtonsoft.Json.Linq.JToken> {{ "hello", "world" }
            }
            };
        }
    }
    public class InjectValue : IValueProvider
    {
        public Type Type { get; set; }
        public BindingContext Context { get; set; }

        public Task<object> GetValueAsync()
        {


            var field = Context.ValueContext.FunctionContext.GetType().GetField("_functionInvocationServices", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            var sp = field.GetValue(Context.ValueContext.FunctionContext) as IServiceProvider;
            return Task.FromResult(sp.GetService(Type));
            //WARNING, this do not use the service provider, a new object is created but not tracked by scoped service provider and disposed ect.
            return Task.FromResult(Context.ValueContext.FunctionContext.CreateObjectInstance(Type));
        }

        public string ToInvokeString()
        {
            return null;
        }
    }
    [Extension(nameof(InjectExtension))]
    public class InjectExtension : IExtensionConfigProvider
    {
     

        public InjectExtension()
        {
            
        }
        public void Initialize(ExtensionConfigContext context)
        {
     

            context.AddBindingRule<InjectAttribute>()
                .Bind(new InjectBindingProvider());
        }

    }
    
}
