using NUnit.Framework;
using Rhino.Mocks;
using System;
using System.Collections.Generic;
using TestFramework.Model.Services.Geolocation;
using TestFramework.Services.BluetoothLock;
using TINK.Model.Bike.BluetoothLock;
using TINK.Model.Device;
using TINK.Model.State;
using TINK.Model.User;
using TINK.ViewModel.Bikes;
using TINK.ViewModel.Bikes.Bike.BluetoothLock;
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;

namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
{
    /// <summary>
    /// Moved to TestShareeLib (.Net Core)
    /// </summary>
    [TestFixture]
    public class TestRequestHandlerFactory
    {
        [Test]
        public void TestCreate()
        {
            // Verify handler for disposable bike.
            var bike = new BikeInfoMutable(
                new BikeInfo("22", 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "12"),
                "My Station Name");
            Assert.AreEqual(InUseStateEnum.Disposable, bike.State.Value);
            Assert.AreEqual(LockingState.Disconnected, bike.LockInfo.State);
            Assert.AreEqual(
                typeof(DisposableDisconnected),
                RequestHandlerFactory.Create(
                    bike,
                    () => false, // isConnectedDelegate
                    (connected) => null, // connectorFactory
                    new GeolocationMock(), // geolocation
                    new LocksServiceMock(), // LockService
                    null, // viewUpdateManager
                    NSubstitute.Substitute.For<ISmartDevice>(),
                    null /* viewService */ ,
                    MockRepository.GenerateStub<IBikesViewModel>(),
                    MockRepository.GenerateStub<IUser>()).GetType());

            // Verify handler for requested bike with state unknown.
            bike = new BikeInfoMutable(
                new BikeInfo("22", 0 /* lock Id */, new Guid(), /*K User*/ null, /*K Admin*/ null, /*K Seed*/  null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>(), TINK.Model.Bike.WheelType.Mono, TINK.Model.Bike.TypeOfBike.Allround),
                "My Station Name");
            Assert.AreEqual(
                typeof(ReservedDisconnected),
                RequestHandlerFactory.Create(
                    bike,
                    () => false, // isConnectedDelegate
                    (connected) => null, // connectorFactory
                    new GeolocationMock(), // geolocation
                    new LocksServiceMock(), // LockService
                    null, // viewUpdateManager
                    NSubstitute.Substitute.For<ISmartDevice>(),
                    null /* viewService */,
                    MockRepository.GenerateStub<IBikesViewModel>(),
                    MockRepository.GenerateStub<IUser>()).GetType());

            // Verify handler for requested bike with state closed.
            bike = new BikeInfoMutable(
                new BikeInfo("22", 0 /* lock Id*/, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>(), TINK.Model.Bike.WheelType.Mono, TINK.Model.Bike.TypeOfBike.Allround), 
                "My Station Name");
            bike.LockInfo.State = LockingState.Closed;
            Assert.AreEqual(
                typeof(ReservedClosed),
                RequestHandlerFactory.Create(
                    bike,
                    () => false, // isConnectedDelegate
                    (connected) => null, // connectorFactory
                    new GeolocationMock(), // geolocation
                    new LocksServiceMock(), // LockService
                    null, // viewUpdateManager
                    NSubstitute.Substitute.For<ISmartDevice>(),
                    null /* viewService */,
                    MockRepository.GenerateStub<IBikesViewModel>(),
                    MockRepository.GenerateStub<IUser>()).GetType());

            // Verify handler for requested bike with state open.
            bike = new BikeInfoMutable(
                new BikeInfo("22", 0 /* lock Id*/, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>(), TINK.Model.Bike.WheelType.Mono, TINK.Model.Bike.TypeOfBike.Allround),
                "My Station Name");
            bike.LockInfo.State = LockingState.Open;
            Assert.AreEqual(
                typeof(ReservedOpen),
                RequestHandlerFactory.Create(
                    bike,
                    () => false, // isConnectedDelegate
                    (connected) => null, // connectorFactory
                    new GeolocationMock(), // geolocation
                    new LocksServiceMock(), // LockService
                    null, // viewUpdateManager
                    NSubstitute.Substitute.For<ISmartDevice>(),
                    null /* viewService */,
                    MockRepository.GenerateStub<IBikesViewModel>(),
                    MockRepository.GenerateStub<IUser>()).GetType());

            // Verify handler for booked bike with state closed.
            bike = new BikeInfoMutable(
                new BikeInfo("22", 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>(), TINK.Model.Bike.WheelType.Mono, TINK.Model.Bike.TypeOfBike.Allround), 
                "My Station Name");
            bike.LockInfo.State = LockingState.Closed;
            Assert.AreEqual(
                typeof(BookedClosed),
                RequestHandlerFactory.Create(
                    bike,
                    () => false, // isConnectedDelegate
                    (connected) => null, // connectorFactory
                    new GeolocationMock(), // geolocation
                    new LocksServiceMock(), // LockService
                    null, // viewUpdateManager
                    NSubstitute.Substitute.For<ISmartDevice>(),
                    null /* viewService */,
                    MockRepository.GenerateStub<IBikesViewModel>(),
                    MockRepository.GenerateStub<IUser>()).GetType());

            // Verify handler for booked bike with state open.
            bike = new BikeInfoMutable(
                new BikeInfo("22", 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>(), TINK.Model.Bike.WheelType.Mono, TINK.Model.Bike.TypeOfBike.Allround), 
                "My Station Name");
            bike.LockInfo.State = LockingState.Open;
            Assert.AreEqual(
                typeof(BookedOpen),
                RequestHandlerFactory.Create(
                    bike,
                    () => false, // isConnectedDelegate
                    (connected) => null, // connectorFactory
                    new GeolocationMock(), // geolocation
                    new LocksServiceMock(), // LockService
                    null, // viewUpdateManager
                    NSubstitute.Substitute.For<ISmartDevice>(),
                    null /* viewService */,
                    MockRepository.GenerateStub<IBikesViewModel>(),
                    MockRepository.GenerateStub<IUser>()).GetType());

            // Verify handler for booked bike with state unknown.
            bike = new BikeInfoMutable(
                new BikeInfo("22", 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>(), TINK.Model.Bike.WheelType.Mono, TINK.Model.Bike.TypeOfBike.Allround), 
                "My Station Name");
            
            Assert.AreEqual(
                typeof(BookedDisconnected),
                RequestHandlerFactory.Create(
                    bike, 
                    ()=> false, // isConnectedDelegate
                    (connected) => null, // connectorFactory
                    new GeolocationMock(), // geolocation
                    new LocksServiceMock(), // LockService
                    null, // viewUpdateManager
                    NSubstitute.Substitute.For<ISmartDevice>(),
                    null /* viewService */,
                    MockRepository.GenerateStub<IBikesViewModel>(),
                    MockRepository.GenerateStub<IUser>()).GetType());
        }
    }
}