using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;

namespace Prometheus.HttpMetrics
{
    /// <summary>
    /// If routing data is available before executing the inner handler, this routing data is captured
    /// and can be used later by other middlewares that wish not to be affected by runtime changes to routing data.
    /// </summary>
    /// <remarks>
    /// This is intended to be executed after the .UseRouting() middleware that performs ASP.NET Core 3 endpoint routing.
    /// 
    /// The captured route data is stored in the context via ICapturedRouteDataFeature.
    /// </remarks>
    internal sealed class CaptureRouteDataMiddleware
    {
        private readonly RequestDelegate _next;

        public CaptureRouteDataMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public Task Invoke(HttpContext context)
        {
            TryCaptureRouteData(context);

            return _next(context);
        }

        private static void TryCaptureRouteData(HttpContext context)
        {
            var routeData = context.GetRouteData();

            if (routeData == null || routeData.Values.Count <= 0)
                return;

            var capturedRouteData = new CapturedRouteDataFeature();

            foreach (var pair in routeData.Values)
                capturedRouteData.Values.Add(pair.Key, pair.Value);

            context.Features.Set<ICapturedRouteDataFeature>(capturedRouteData);
        }
    }
}
