﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using Moq;

namespace Barsik.Client.Tests
{
    [TestFixture]
    public class ResponseReceiverTests
    {
        SomeRequest request;
        IServerAddress serverAddress;  
        IPacketReceiver packetReceiver;
        IPacketConverter packetConverter;

        ResponseReveiver responseReceiver;

        [SetUp]
        public void SetUp()
        {
            request = new SomeRequest();
            serverAddress = Mock.Of<IServerAddress>();
            packetReceiver = Mock.Of<IPacketReceiver>();
            packetConverter = Mock.Of<IPacketConverter>();
            responseReceiver = new ResponseReveiver(packetReceiver, packetConverter);
        }

        [Test]
        public async Task Should_Convert_Request_To_Packet()
        {
            await responseReceiver.ReceiveResponseAsync(serverAddress, request, typeof(SomeResponse));

            Mock.Get(packetConverter).Verify(c => c.ToPacket(request), Times.Once);
        }

        [Test]
        public async Task Should_Pass_RequestPacket_To_PacketReceiver()
        {
            var requestPacket = Mock.Of<IPacket>();
            Mock.Get(packetConverter).Setup(c => c.ToPacket(request)).Returns(requestPacket);

            await responseReceiver.ReceiveResponseAsync(serverAddress, request, typeof(SomeResponse));

            Mock.Get(packetReceiver).Verify(r => r.ReceivePacketAsync(It.IsAny<IServerAddress>(), requestPacket), Times.Once);
        }

        [Test]
        public async Task Should_Receive_ResponsePacket_From_ServerAddress()
        {
            await responseReceiver.ReceiveResponseAsync(serverAddress, request, typeof(SomeResponse));

            Mock.Get(packetReceiver).Verify(r => r.ReceivePacketAsync(serverAddress, It.IsAny<IPacket>()), Times.Once);
        }

        [Test]
        public async Task Should_Convert_ResponsePacket_To_Response()
        {
            var responsePacket = Mock.Of<IPacket>();
            Mock.Get(packetReceiver).Setup(r => r.ReceivePacketAsync(It.IsAny<IServerAddress>(), It.IsAny<IPacket>())).ReturnsAsync(responsePacket);

            await responseReceiver.ReceiveResponseAsync(serverAddress, request, typeof(SomeResponse));

            Mock.Get(packetConverter).Verify(c => c.ToObject(responsePacket, typeof(SomeResponse)), Times.Once);
        }

        [Test]
        public async Task Should_Return_Response_Converted_From_ResponsePacket()
        {
            var response = new SomeResponse();
            Mock.Get(packetConverter).Setup(c => c.ToObject(It.IsAny<IPacket>(), response.GetType())).Returns(response);

            var receivedResponse = await responseReceiver.ReceiveResponseAsync(serverAddress, request, typeof(SomeResponse));

            Assert.That(receivedResponse, Is.SameAs(response));
        }

        public class SomeRequest
        {
        }

        public class SomeResponse
        {
        }
    }
}
