using NUnit.Framework;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using RebootKit.Engine.Foundation;

namespace Tests.Runtime.Engine {
    internal interface ITestService {
        int Value();
    }

    internal class TestServiceA : ITestService {
        public const int k_ReturnValue = 1;

        public int Value() {
            return k_ReturnValue;
        }
    }

    internal class TestServiceB : ITestService {
        public const int k_ReturnValue = 2;

        public int Value() {
            return k_ReturnValue;
        }
    }

    public class DIContextTests {
        [Test]
        public void Single_Bind_And_Resolve() {
            DIContext context = new();
            context.Bind<ITestService>(new TestServiceA());

            ITestService testService = context.Resolve<ITestService>();
            Assert.IsNotNull(testService, "Resolved service is null!");

            Assert.IsTrue(testService.Value() == TestServiceA.k_ReturnValue, "Invalid return value of resolved service");
        }

        private class TestObject {
            [Inject]
            public ITestService Service;
        }

        [Test]
        public void Single_Bind_And_Field_Inject() {
            DIContext context = new();
            context.Bind<ITestService>(new TestServiceB());

            TestObject obj = new();
            context.Inject(obj);
            
            Assert.IsNotNull(obj.Service, "obj.Service != null");
            Assert.IsTrue(obj.Service.Value() == TestServiceB.k_ReturnValue);
        }
        
        
        private class TestObjectMethod {
            public ITestService Service;

            [Inject]
            public void Setup(ITestService service) {
                Service = service;
            }
        }

        [Test]
        public void Single_Bind_And_Method_Inject() {
            DIContext context = new();
            context.Bind<ITestService>(new TestServiceA());

            TestObjectMethod obj = new();
            context.Inject(obj);
            
            Assert.IsNotNull(obj.Service, "obj.Service != null");
            Assert.IsTrue(obj.Service.Value() == TestServiceA.k_ReturnValue);
        }
    }
}