using System.Diagnostics.Contracts;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using System.Web.Http.Routing;

namespace PlatezhkaDemoApi
{
    public class ApiHttpRoute : HttpMessageHandler
    {
        private IHttpControllerSelector _controllerSelector;
        private readonly HttpConfiguration _configuration;

        public ApiHttpRoute(HttpConfiguration configuration)
        {
            _configuration = configuration;
        }

        private IHttpControllerSelector ControllerSelector => _controllerSelector ??
                                                              (_controllerSelector = _configuration.Services.GetHttpControllerSelector());

        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            return SendAsyncInternal(request, cancellationToken);
        }

        private Task<HttpResponseMessage> SendAsyncInternal(HttpRequestMessage request, CancellationToken cancellationToken)
        {

            IHttpRouteData routeData = request.GetRouteData();
            Contract.Assert(routeData != null);

            HttpControllerDescriptor httpControllerDescriptor;
            string controllerName = ControllerHelper.GetControllerNameFromRequest(request);
            var httpControllers = ControllerSelector.GetControllerMapping();
            httpControllers.TryGetValue(controllerName, out httpControllerDescriptor);
            if (httpControllerDescriptor == null)
            {
                return Task.Run(() => request.CreateResponse(HttpStatusCode.BadRequest), cancellationToken);
            }
            IHttpController httpController = httpControllerDescriptor.CreateController(request);

            HttpControllerContext controllerContext =
                new HttpControllerContext(_configuration, routeData, request)
                {
                    Controller = httpController,
                    ControllerDescriptor = httpControllerDescriptor
                };

            return httpController.ExecuteAsync(controllerContext, cancellationToken);
        }
    }
}