﻿using AngleSharp;
using AngleSharp.Html.Dom;
using AngleSharp.Io;
using GenderPayGap.Extensions;
using Microsoft.Net.Http.Headers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;

namespace GenderPayGap.Sitemap
{
    public static partial class Extensions
    {
        public static async Task<IHtmlDocument> GetDocumentAsync(this HttpResponseMessage response)
        {
            var content = await response.Content.ReadAsStringAsync();

            var document = await BrowsingContext.New()
                .OpenAsync(ResponseFactory, CancellationToken.None);
            return (IHtmlDocument)document;

            void ResponseFactory(VirtualResponse htmlResponse)
            {
                htmlResponse
                    .Address(response.RequestMessage.RequestUri)
                    .Status(response.StatusCode);

                MapHeaders(response.Headers);
                MapHeaders(response.Content.Headers);

                htmlResponse.Content(content);

                void MapHeaders(System.Net.Http.Headers.HttpHeaders headers)
                {
                    foreach (var header in headers)
                    {
                        foreach (var value in header.Value)
                        {
                            htmlResponse.Header(header.Key, value);
                        }
                    }
                }
            }
        }

        public static IEnumerable<SetCookieHeaderValue> GetCookies(this HttpResponseHeaders responseHeaders, params string[] cookieNames)
        {
            if (responseHeaders.TryGetValues("Set-Cookie", out IEnumerable<string> newCookies))
            {
                foreach (var setCookie in SetCookieHeaderValue.ParseList(newCookies.ToList()))
                    if (cookieNames==null || !cookieNames.Any() || cookieNames.Any(c => setCookie.Name.ToString().Like(c)))
                        yield return setCookie;
            }
        }

        public static IEnumerable<NameValueElement> GetHeaders(this HttpResponseHeaders responseHeaders, params string[] headerNames)
        {
            foreach (var responseHeader in responseHeaders)
                if (!responseHeader.Key.EqualsI("Set-Cookie"))
                    if (headerNames == null || !headerNames.Any() || headerNames.Any(h => responseHeader.Key.Like(h)))
                        yield return new NameValueElement(responseHeader.Key, responseHeader.Value.ToDelimitedString("; "));
        }

        public static string GetCookieHeader(this IEnumerable<SetCookieHeaderValue> cookies)
        {
            var uri = new Uri("http://localhost");
            var cookieContainer = new CookieContainer();

            foreach (var cookie in cookies)
                cookieContainer.Add(uri,new Cookie(cookie.Name.ToString(), cookie.Value.ToString()));

            return cookieContainer.GetCookieHeader(uri);
        }
    }
}
