using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Core.Composing;
namespace Umbraco.Core
{
///
/// Provides extension methods to the class.
///
public static class ServiceProviderExtensions
{
///
/// Creates an instance with arguments.
///
/// The type of the instance.
/// The factory.
/// Arguments.
/// An instance of the specified type.
///
/// Throws an exception if the factory failed to get an instance of the specified type.
/// The arguments are used as dependencies by the factory.
///
public static T CreateInstance(this IServiceProvider serviceProvider, params object[] args)
where T : class
=> (T)serviceProvider.CreateInstance(typeof(T), args);
///
/// Creates an instance of a service, with arguments.
///
///
/// The type of the instance.
/// Named arguments.
/// An instance of the specified type.
///
/// The instance type does not need to be registered into the factory.
/// The arguments are used as dependencies by the factory. Other dependencies
/// are retrieved from the factory.
///
public static object CreateInstance(this IServiceProvider serviceProvider, Type type, params object[] args)
{
// LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities
// including the most annoying one, which is that it does not work on singletons (hard to fix)
//return factory.GetInstance(type, args);
// this method is essentially used to build singleton instances, so it is assumed that it would be
// more expensive to build and cache a dynamic method ctor than to simply invoke the ctor, as we do
// here - this can be discussed
// TODO: we currently try the ctor with most parameters, but we could want to fall back to others
//var ctor = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public).OrderByDescending(x => x.GetParameters().Length).FirstOrDefault();
//if (ctor == null) throw new InvalidOperationException($"Could not find a public constructor for type {type.FullName}.");
//var ctorParameters = ctor.GetParameters();
//var ctorArgs = new object[ctorParameters.Length];
//var availableArgs = new List