using System;
using Microsoft.Extensions.DependencyInjection;
namespace Kyoo.Abstractions.Controllers
{
	/// 
	/// A list of constant priorities used for 's .
	/// It also contains helper methods for creating new .
	/// 
	public static class SA
	{
		public const int Before = 5000;
		public const int Routing = 4000;
		public const int StaticFiles = 3000;
		public const int Authentication = 2000;
		public const int Authorization = 1000;
		public const int Endpoint = 0;
		public const int After = -1000;
		/// 
		/// Create a new .
		/// 
		/// The action to run
		/// The priority of the new action
		/// A new 
		public static StartupAction New(Action action, int priority) 
			=> new(action, priority);
		
		/// 
		/// Create a new .
		/// 
		/// The action to run
		/// The priority of the new action
		/// A dependency that this action will use.
		/// A new 
		public static StartupAction New(Action action, int priority) 
			=> new(action, priority);
		
		/// 
		/// Create a new .
		/// 
		/// The action to run
		/// The priority of the new action
		/// A dependency that this action will use.
		/// A second dependency that this action will use.
		/// A new 
		public static StartupAction New(Action action, int priority) 
			=> new(action, priority);
		
		/// 
		/// Create a new .
		/// 
		/// The action to run
		/// The priority of the new action
		/// A dependency that this action will use.
		/// A second dependency that this action will use.
		/// A third dependency that this action will use.
		/// A new 
		public static StartupAction New(Action action, int priority) 
			=> new(action, priority);
	}
	
	
	/// 
	/// An action executed on kyoo's startup to initialize the asp-net container.
	/// 
	/// 
	/// This is the base interface, see  for a simpler use of this.
	/// 
	public interface IStartupAction
	{
		/// 
		/// The priority of this action. The actions will be executed on descending priority order.
		/// If two actions have the same priority, their order is undefined.
		/// 
		int Priority { get; }
		/// 
		/// Run this action to configure the container, a service provider containing all services can be used.
		/// 
		/// The service provider containing all services can be used.
		void Run(IServiceProvider provider);
	}
		
	/// 
	/// A  with no dependencies.
	/// 
	public class StartupAction : IStartupAction
	{
		/// 
		/// The action to execute at startup.
		/// 
		private readonly Action _action;
		/// 
		public int Priority { get; }
		
		/// 
		/// Create a new .
		/// 
		/// The action to execute on startup.
		/// The priority of this action (see ).
		public StartupAction(Action action, int priority)
		{
			_action = action;
			Priority = priority;
		}
		/// 
		public void Run(IServiceProvider provider)
		{
			_action.Invoke();
		}
	}
	/// 
	/// A  with one dependencies.
	/// 
	/// The dependency to use.
	public class StartupAction : IStartupAction
	{
		/// 
		/// The action to execute at startup.
		/// 
		private readonly Action _action;
		/// 
		public int Priority { get; }
		
		/// 
		/// Create a new .
		/// 
		/// The action to execute on startup.
		/// The priority of this action (see ).
		public StartupAction(Action action, int priority)
		{
			_action = action;
			Priority = priority;
		}
		/// 
		public void Run(IServiceProvider provider)
		{
			_action.Invoke(provider.GetRequiredService());
		}
	}
	
	/// 
	/// A  with two dependencies.
	/// 
	/// The dependency to use.
	/// The second dependency to use.
	public class StartupAction : IStartupAction
	{
		/// 
		/// The action to execute at startup.
		/// 
		private readonly Action _action;
		/// 
		public int Priority { get; }
		/// 
		/// Create a new .
		/// 
		/// The action to execute on startup.
		/// The priority of this action (see ).
		public StartupAction(Action action, int priority)
		{
			_action = action;
			Priority = priority;
		}
		/// 
		public void Run(IServiceProvider provider)
		{
			_action.Invoke(
				provider.GetRequiredService(),
				provider.GetRequiredService()
			);
		}
	}
	
	/// 
	/// A  with three dependencies.
	/// 
	/// The dependency to use.
	/// The second dependency to use.
	/// The third dependency to use.
	public class StartupAction : IStartupAction
	{
		/// 
		/// The action to execute at startup.
		/// 
		private readonly Action _action;
		/// 
		public int Priority { get; }
		
		/// 
		/// Create a new .
		/// 
		/// The action to execute on startup.
		/// The priority of this action (see ).
		public StartupAction(Action action, int priority)
		{
			_action = action;
			Priority = priority;
		}
		/// 
		public void Run(IServiceProvider provider)
		{
			_action.Invoke(
				provider.GetRequiredService(),
				provider.GetRequiredService(),
				provider.GetRequiredService()
			);
		}
	}
}