using FabAccessAPI;
using NUnit.Framework;
using System.Threading.Tasks;
using FabAccessAPI.Schema;

namespace FabAccessAPI_Test.API_TestEnv
{
    [TestFixture, Parallelizable(ParallelScope.Children)]
    [Order(2)]
    public class Machine_Test_Stateless
    {
        [TestCase("Admin1", "MachineA1", true)]
        [TestCase("Admin1", "MachineB1", true)]
        [TestCase("Admin1", "MachineC1", true)]
        [TestCase("ManagerA1", "MachineA1", true)]
        [TestCase("ManagerB1", "MachineB1", true)]
        [TestCase("ManagerC1", "MachineC1", true)]
        [TestCase("ManagerABC1", "MachineA1", true)]
        [TestCase("ManagerABC1", "MachineB1", true)]
        [TestCase("ManagerABC1", "MachineC1", true)]
        [TestCase("MakerA1", "MachineA1", true)]
        [TestCase("MakerB1", "MachineB1", true)]
        [TestCase("MakerC1", "MachineC1", true)]
        [TestCase("GuestA1", "MachineA1", true)]
        [TestCase("GuestB1", "MachineB1", true)]
        [TestCase("GuestC1", "MachineC1", true)]
        [TestCase("MakerQRA", "MachineA1", true)]
        [TestCase("MakerQRB", "MachineB1", true)]
        [TestCase("MakerQRC", "MachineC1", true)]
        [Order(1)]
        public async Task InfoInterface(string username, string machineID, bool expectInterface)
        {
            API api = new API();
            ConnectionData connectionData = TestEnv.CreateConnetionData(username);
            await api.Connect(connectionData);

            Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;

            bool result = !((Machine.InfoInterface_Proxy)machine.Info).IsNull;

            await api.Disconnect();

            Assert.AreEqual(expectInterface, result);
        }

        [TestCase("Admin1", "MachineA1", true)]
        [TestCase("Admin1", "MachineB1", true)]
        [TestCase("Admin1", "MachineC1", true)]
        [TestCase("ManagerA1", "MachineA1", true)]
        [TestCase("ManagerB1", "MachineB1", true)]
        [TestCase("ManagerC1", "MachineC1", true)]
        [TestCase("ManagerABC1", "MachineA1", true)]
        [TestCase("ManagerABC1", "MachineB1", true)]
        [TestCase("ManagerABC1", "MachineC1", true)]
        [TestCase("MakerA1", "MachineA1", false)]
        [TestCase("MakerB1", "MachineB1", false)]
        [TestCase("MakerC1", "MachineC1", false)]
        [TestCase("GuestA1", "MachineA1", false)]
        [TestCase("GuestB1", "MachineB1", false)]
        [TestCase("GuestC1", "MachineC1", false)]
        [TestCase("MakerQRA", "MachineA1", false)]
        [TestCase("MakerQRB", "MachineB1", false)]
        [TestCase("MakerQRC", "MachineC1", false)]
        [Order(2)]
        public async Task ManageInterface(string username, string machineID, bool expectInterface)
        {
            API api = new API();
            ConnectionData connectionData = TestEnv.CreateConnetionData(username);
            await api.Connect(connectionData);

            Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;

            bool result = !((Machine.ManageInterface_Proxy)machine.Manage).IsNull;

            await api.Disconnect();

            Assert.AreEqual(expectInterface, result);
        }

        [TestCase("Admin1", "MachineA1", true)]
        [TestCase("Admin1", "MachineB1", true)]
        [TestCase("Admin1", "MachineC1", true)]
        [TestCase("ManagerA1", "MachineA1", false)]
        [TestCase("ManagerB1", "MachineB1", false)]
        [TestCase("ManagerC1", "MachineC1", false)]
        [TestCase("ManagerABC1", "MachineA1", false)]
        [TestCase("ManagerABC1", "MachineB1", false)]
        [TestCase("ManagerABC1", "MachineC1", false)]
        [TestCase("MakerA1", "MachineA1", false)]
        [TestCase("MakerB1", "MachineB1", false)]
        [TestCase("MakerC1", "MachineC1", false)]
        [TestCase("GuestA1", "MachineA1", false)]
        [TestCase("GuestB1", "MachineB1", false)]
        [TestCase("GuestC1", "MachineC1", false)]
        [TestCase("MakerQRA", "MachineA1", false)]
        [TestCase("MakerQRB", "MachineB1", false)]
        [TestCase("MakerQRC", "MachineC1", false)]
        [Order(3), Ignore("Not Implemented")]
        public async Task AdminInterface(string username, string machineID, bool expectInterface)
        {
            API api = new API();
            ConnectionData connectionData = TestEnv.CreateConnetionData(username);
            await api.Connect(connectionData);

            Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;

            bool result = !((Machine.AdminInterface_Proxy)machine.Admin).IsNull;

            await api.Disconnect();

            Assert.AreEqual(expectInterface, result);
        }

        [TestCase("Admin1", "MachineA1", "Description of MachineA1", @"https://fab-access.readthedocs.io", "CategoryA")]
        [TestCase("Admin1", "MachineB2", "Description of MachineB2", @"https://fab-access.readthedocs.io", "CategoryB")]
        [TestCase("Admin1", "MachineC3", "Description of MachineC3", @"https://fab-access.readthedocs.io", "CategoryC")]
        [Order(4)]
        public async Task ReadMachineData(string username, string machineID, string description, string wiki, string category)
        {
            API api = new API();
            ConnectionData connectionData = TestEnv.CreateConnetionData(username);
            await api.Connect(connectionData);

            Machine machine = (await api.Session.MachineSystem.Info.GetMachine(machineID).ConfigureAwait(false)).Just;

            await api.Disconnect();

            Assert.Multiple(() =>
            {
                Assert.AreEqual(machineID, machine.Id);
                Assert.AreEqual(description, machine.Description);
                Assert.AreEqual(wiki, machine.Wiki);
                Assert.AreEqual(category, machine.Category);
            });
        }
    }

}