using Netmash.Extensions.Http;
using NetworkResurrector.Agent.PublishedLanguage.Commands;
using NetworkResurrector.Agent.PublishedLanguage.Dto;
using NetworkResurrector.Agent.PublishedLanguage.Events;
using NetworkResurrector.Agent.Wrapper.Constants;
using NetworkResurrector.Agent.Wrapper.Models;
using NetworkResurrector.Agent.Wrapper.Services.Internal;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace NetworkResurrector.Agent.Wrapper.Services
{
    internal class ResurrectorAgentService : IResurrectorAgentService
    {
        private const string _contentType = "application/json";
        private readonly HttpClient _httpClient;

        public ResurrectorAgentService(HttpClient httpClient, ServiceConfiguration configuration, HttpHeadersService headersService)
        {
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(_contentType));

            if (configuration.ForwardHeaders)
            {
                headersService.SetHeadersFromContext(httpClient);
            }

            _httpClient = httpClient;
        }

        private void SetHttpClientBaseAddress(string ipAddressOrMachineName, int agentPort)
        {
            var baseAddress = $"http://{ipAddressOrMachineName}:{agentPort}";
            _httpClient.BaseAddress = new Uri(baseAddress);
        }

        public async Task<ShutdownResult> Shutdown(string ipAddressOrMachineName, int agentPort, ActionOwner actionOwner = null, ActionOptions actionOptions = null)
        {
            SetHttpClientBaseAddress(ipAddressOrMachineName, agentPort);

            var body = new Shutdown { Owner = actionOwner, Options = actionOptions };
            var result = await _httpClient.ExecutePostRequest<ShutdownResult, Shutdown>(ApiRoutes.Shutdown, body);
            return result;
        }

        public async Task<RestartResult> Restart(string ipAddressOrMachineName, int agentPort, ActionOwner actionOwner = null, ActionOptions actionOptions = null)
        {
            SetHttpClientBaseAddress(ipAddressOrMachineName, agentPort);

            var body = new Restart { Owner = actionOwner, Options = actionOptions };
            var result = await _httpClient.ExecutePostRequest<RestartResult, Restart>(ApiRoutes.Restart, body);
            return result;
        }

        public async Task<SleepResult> Sleep(string ipAddressOrMachineName, int agentPort, ActionOwner actionOwner = null, ActionOptions actionOptions = null)
        {
            SetHttpClientBaseAddress(ipAddressOrMachineName, agentPort);

            var body = new Sleep { Owner = actionOwner, Options = actionOptions };
            var result = await _httpClient.ExecutePostRequest<SleepResult, Sleep>(ApiRoutes.Sleep, body);
            return result;
        }

        public async Task<LogoutResult> Logout(string ipAddressOrMachineName, int agentPort, ActionOwner actionOwner = null)
        {
            SetHttpClientBaseAddress(ipAddressOrMachineName, agentPort);

            var body = new Logout { Owner = actionOwner };
            var result = await _httpClient.ExecutePostRequest<LogoutResult, Logout>(ApiRoutes.Logout, body);
            return result;
        }

        public async Task<LockResult> Lock(string ipAddressOrMachineName, int agentPort, ActionOwner actionOwner = null)
        {
            SetHttpClientBaseAddress(ipAddressOrMachineName, agentPort);

            var body = new Lock { Owner = actionOwner };
            var result = await _httpClient.ExecutePostRequest<LockResult, Lock>(ApiRoutes.Lock, body);
            return result;
        }

        public async Task<CancelResult> Cancel(string ipAddressOrMachineName, int agentPort, ActionOwner actionOwner = null)
        {
            SetHttpClientBaseAddress(ipAddressOrMachineName, agentPort);

            var body = new Cancel { Owner = actionOwner };
            var result = await _httpClient.ExecutePostRequest<CancelResult, Cancel>(ApiRoutes.Cancel, body);
            return result;
        }
    }
}
