using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using CryptoExchange.Net.Interfaces;

namespace CryptoExchange.Net.Requests
{
    /// <summary>
    /// Request object, wrapper for HttpRequestMessage
    /// </summary>
    public class Request : IRequest
    {
        private readonly HttpRequestMessage _request;
        private readonly HttpClient _httpClient;

        /// <summary>
        /// Create request object for web request
        /// </summary>
        public Request(HttpRequestMessage request, HttpClient client, int requestId)
        {
            _httpClient = client;
            _request = request;
            RequestId = requestId;
        }
        
        /// <inheritdoc />
        public string? Content { get; private set; }

        /// <inheritdoc />
        public MediaTypeWithQualityHeaderValue Accept
        {
            set => _request.Headers.Accept.Add(value);
        }

        /// <inheritdoc />
        public HttpMethod Method
        {
            get => _request.Method;
            set => _request.Method = value;
        }

        /// <inheritdoc />
        public Uri Uri => _request.RequestUri!;

        /// <inheritdoc />
        public Version HttpVersion => _request.Version!;

        /// <inheritdoc />
        public int RequestId { get; }

        /// <inheritdoc />
        public void SetContent(string data, Encoding? encoding, string contentType)
        {
            Content = data;
            _request.Content = new StringContent(data, encoding ?? Encoding.UTF8, contentType);
            if (encoding == null)
                _request.Content.Headers.ContentType!.CharSet = null;
        }

        /// <inheritdoc />
        public void AddHeader(string key, string value)
        {
            _request.Headers.Add(key, value);
        }

        /// <inheritdoc />
        public HttpRequestHeaders GetHeaders()
        {
            return _request.Headers;
        }

        /// <inheritdoc />
        public void SetContent(byte[] data)
        {
            _request.Content = new ByteArrayContent(data);
        }

        /// <inheritdoc />
        public async Task<IResponse> GetResponseAsync(CancellationToken cancellationToken)
        {
            var response = await _httpClient.SendAsync(_request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
            
            return new Response(response);
        }
    }
}
