using System.Linq;
using NUnit.Framework;
using TINK.Repository;
using TINK.Repository.Response;

namespace TestTINKLib.Fixtures.ObjectTests.Connector.Request
{
    [TestFixture]
    public class TestCopriCallsStatic
    {
        [Test]
        public void TestDeserializeObjectBikesAvailableValidResponse()
        {
            const string VALID_RESPONSE = @"
              {
	            ""shareejson"": {

                    ""authcookie"": 0,
		            ""apiserver"": ""https://tinkwwp.copri-bike.de"",
		            ""response"": ""bikes_available"",
		            ""bikes"": {
                            ""3399"": {
                            ""description"": ""Cargo Trike"",
				            ""bike"": ""26"",
				            ""state"": ""available"",
				            ""gps"" : { ""latitude"": ""47.6586936667"", ""longitude"": ""9.16863116667"" },
				            ""station"" : ""4""
    
                        },
                    },
		            ""response_state"": ""OK"",
                    ""copri_version"" : ""4.1.0.0""
                }
            }
            ";

            // Ensure that answer holds a valid bike.
            var l_oBike = CopriCallsStatic.DeserializeResponse<BikesAvailableResponse>(VALID_RESPONSE).bikes.FirstOrDefault().Value;
            Assert.NotNull(l_oBike, "Response must contain at leas one bike.");
            Assert.Greater(l_oBike.description.Length, 0, "Bike despcription must never be empty.");
            Assert.AreEqual(l_oBike.bike, "26");
            Assert.That(
                l_oBike.station, 
                Is.EqualTo("4"),
                "Station index must never be negative");
            Assert.AreEqual("available", l_oBike.state);
            Assert.That(l_oBike.gps, Is.Not.Null, "Gps position must never be empty.");
        }

        [Test]
        public void TestDeserializeObjectBikesAvailableValidResponse_NoDescription()
        {
            const string INVALID_RESPONSE = @"
              {
	            ""shareejson"": {

                    ""authcookie"": 0,
		            ""apiserver"": ""https://tinkwwp.copri-bike.de"",
		            ""response"": ""bikes_available"",
		            ""bikes"": {
                            ""3399"": {
				            ""bike"": 26,
				            ""state"": ""available"",
				            ""gps"" : { ""latitude"": ""47.6586936667"", ""longitude"": ""9.16863116667"" },
				            ""station"" : 4
    
                        },
                    },
		            ""response_state"": ""OK"",
                    ""copri_version"" : ""4.1.0.0"",
                }
            }
            ";

            // Ensure that answer holds a valid bike.
            var l_oBike = CopriCallsStatic.DeserializeResponse<BikesAvailableResponse>(INVALID_RESPONSE).bikes.FirstOrDefault().Value;
            Assert.NotNull(l_oBike, "Response must contain at leas one bike.");
            Assert.IsNull(l_oBike.description);
            Assert.That(l_oBike.bike, Is.Not.Null);
            Assert.That(l_oBike.station, Is.Not.Null);
            Assert.AreEqual("available", l_oBike.state);
            Assert.That(l_oBike.gps, Is.Not.Null, "Gps position must never be empty.");
        }

        [Test]
        public void TestDeserializeObjectBikesAvailableValidResponse_NoBikeId()
        {
            const string VALID_RESPONSE = @"
            {
	            ""shareejson"": {

                    ""authcookie"": 0,
		            ""apiserver"": ""https://tinkwwp.copri-bike.de"",
		            ""response"": ""bikes_available"",
		            ""bikes"": {
                            ""3399"": {
                            ""description"": ""Cargo Trike"",
				            ""state"": ""available"",
				            ""gps"" : { ""latitude"": ""47.6586936667"", ""longitude"": ""9.16863116667"" },
				            ""station"" : ""4""
                        },
                    },
		            ""response_state"": ""OK"",
                    ""copri_version"" : ""4.1.0.0"",
                }
            }";

            // Ensure that answer holds a valid bike.
            var l_oBike = CopriCallsStatic.DeserializeResponse<BikesAvailableResponse>(VALID_RESPONSE).bikes.FirstOrDefault().Value;
            Assert.NotNull(l_oBike, "Response must contain at leas one bike.");
            Assert.Greater(l_oBike.description.Length, 0, "Bike despcription must never be empty.");
            Assert.That(l_oBike.bike, Is.Null);
            Assert.That(l_oBike.station, Is.Not.Null);
            Assert.AreEqual("available", l_oBike.state);
            Assert.That(l_oBike.gps, Is.Not.Null, "Gps position must never be empty.");
        }

        [Test]
        public void TestDeserializeObjectBikesOccupiedValidResponse()
        {
            const string VALID_RESPONSE = @"
            {
	            ""shareejson"": {
                    ""response_state"": ""OK"",
		            ""bikes_occupied"": {
                            ""87781"": {
                                ""timeCode"": ""3630"",
				                ""state"": ""occupied"",
				                ""station"" : ""5"",
				                ""description"": ""Cargo Long"",
				                ""start_time"": ""2017-11-28 11:01:51.637747+01"",
				                ""bike"": ""8""
                        },
			                ""87782"": {
                                ""timeCode"": ""2931"",
				                ""state"": ""occupied"",
				                ""station"" : ""4"",
				                ""description"": ""Cargo Long"",
				                ""start_time"": ""2017-11-28 13:06:55.147368+01"",
				                ""bike"": ""7""
                            }
                        },
		            ""authcookie"": ""b76b97e43a2d76b8499f32e6dd597af8"",
		            ""response"": ""user_bikes_occupied"",
		            ""apiserver"": ""https://tinkwwp.copri-bike.de"",
                    ""copri_version"" : ""4.1.0.0"",
                }
            }";

            // Ensure that answer holds a valid bike.
            var l_oBike = CopriCallsStatic.DeserializeResponse<BikesReservedOccupiedResponse>(VALID_RESPONSE).bikes_occupied.FirstOrDefault().Value;
            Assert.NotNull(l_oBike, "Response must contain at leas one bike.");
            Assert.Greater(l_oBike.description.Length, 0, "Bike despcription must never be empty.");
            Assert.That(l_oBike.bike, Is.Not.Null);
            Assert.That(l_oBike.station, Is.Not.Null);
            Assert.Greater(l_oBike.state.Length, 0, "State info must never be null or empty.");
            // Todo: Requested bikes do not have a gps position. What is about booked bikes?
            // Assert.Greater(l_oBike.gps.Length, 0, "Gps position must never be empty.");
            Assert.Greater(l_oBike.start_time.Length, 0, "Time when request/ booking was performed must never be null or empty.");
            Assert.Greater(l_oBike.timeCode.Length, 0, "Booking code must never be null or empty.");
        }
    }
}