using Edge.Core.Database.Configuration.Models;
using Edge.Core.IndustryStandardInterface.Pump;
using Edge.Core.Processor;
using Edge.Core.Processor.Communicator;
using Edge.Core.Processor.Dispatcher;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Edge.Core.Test
{
    [TestClass]
    public class ObjectInstanceCreatorUnitTest
    {
        public class InnerOb
        {
            public int Height { get; set; }
            public bool? Female { get; set; }
            //public InnerOb(int height, bool? isFemale)
            //{
            //    this.Height = height;
            //    this.Female = isFemale;
            //}
        }
        public class SimpleObject
        {
            public int Age { get; set; }
            public string Name { get; set; }
            public InnerOb Inner { get; set; }
            public SimpleObject(int age, string name, InnerOb inner)
            {
                this.Age = age;
                this.Name = name;
                this.Inner = inner;
            }

            public SimpleObject(int age, InnerOb inner)
            {
                this.Age = age;
                this.Inner = inner;
            }

            public SimpleObject(InnerOb inner, int age)
            {
                this.Age = age;
                this.Inner = inner;
            }
        }


        public class InnerOb_Generic<T>
        {
            public int Height { get; set; }
            public bool? Female { get; set; }
            public T CheckGenericTypeParameter { get; set; }

            public InnerOb_Generic() { }
        }

        public class SimpleObject_Generic<T>
        {
            public int Age { get; set; }
            public string Name { get; set; }
            public InnerOb_Generic<T> Inner { get; set; }
            public SimpleObject_Generic(InnerOb_Generic<T> inner, int age, string name)
            {
                this.Age = age;
                this.Name = name;
                this.Inner = inner;
            }

            public SimpleObject_Generic(InnerOb_Generic<T> inner, int age)
            {
                this.Age = age;
                this.Inner = inner;
            }

            public SimpleObject_Generic(int age, InnerOb_Generic<T> inner, string name)
            {
                this.Age = age;
                this.Name = name;
                this.Inner = inner;
            }

            public SimpleObject_Generic(string name, InnerOb_Generic<T> inner, int age)
            {
                this.Age = age;
                this.Name = name;
                this.Inner = inner;
            }

            public SimpleObject_Generic(InnerOb_Generic<T> inner, string name, int age)
            {
                this.Age = age;
                this.Name = name;
                this.Inner = inner;
            }
        }

        [TestMethod]
        public void SimpleObject_TestMethod1()
        {
            var obj = ObjectInstanceCreator.Create<SimpleObject>("[12,\"sss\",{\"Height\":999,\"Female\":true}]", null, null);
            Assert.AreEqual(true, obj != null);
            Assert.AreEqual(true, obj.Inner != null);
            Assert.AreEqual(true, obj.Age == 12);
            Assert.AreEqual(true, obj.Name == "sss");
            Assert.AreEqual(true, obj.Inner.Height == 999);
            Assert.AreEqual(true, obj.Inner.Female.Value == true);
        }

        [TestMethod]
        public void SimpleObject_TestMethod3()
        {
            var obj = (SimpleObject)ObjectInstanceCreator.Create(typeof(SimpleObject).FullName, "[12,\"sss\",{\"Height\":999,\"Female\":true}]", null, null);
            Assert.AreEqual(true, obj != null);
            Assert.AreEqual(true, obj.Inner != null);
            Assert.AreEqual(true, obj.Age == 12);
            Assert.AreEqual(true, obj.Name == "sss");
            Assert.AreEqual(true, obj.Inner.Height == 999);
            Assert.AreEqual(true, obj.Inner.Female.Value == true);
        }

        [TestMethod]
        public void SimpleObject_TestMethod6()
        {
            var obj = ObjectInstanceCreator.Create<SimpleObject>("[12,{\"Height\":999,\"Female\":true}]", null, null);
            Assert.AreEqual(true, obj != null);
            Assert.AreEqual(true, obj.Inner != null);
            Assert.AreEqual(true, obj.Age == 12);
            Assert.AreEqual(true, obj.Name == null);
            Assert.AreEqual(true, obj.Inner.Height == 999);
            Assert.AreEqual(true, obj.Inner.Female.Value == true);
        }

        [TestMethod]
        public void SimpleObject_TestMethod7()
        {
            var obj = (SimpleObject)ObjectInstanceCreator.Create(typeof(SimpleObject).FullName, "[12,{\"Height\":999,\"Female\":true}]", null, null);
            Assert.AreEqual(true, obj != null);
            Assert.AreEqual(true, obj.Inner != null);
            Assert.AreEqual(true, obj.Age == 12);
            Assert.AreEqual(true, obj.Name == null);
            Assert.AreEqual(true, obj.Inner.Height == 999);
            Assert.AreEqual(true, obj.Inner.Female.Value == true);
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void SimpleObject_TestMethod9()
        {
            var obj = ObjectInstanceCreator.Create<SimpleObject>("[12,12,{\"Height\":999,\"Female\":true}]", null, null);
            Assert.AreEqual(true, obj != null);
            Assert.AreEqual(true, obj.Inner != null);
            Assert.AreEqual(true, obj.Age == 12);
            Assert.AreEqual(true, obj.Name == "sss");
            Assert.AreEqual(true, obj.Inner.Height == 999);
            Assert.AreEqual(true, obj.Inner.Female.Value == true);
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void SimpleObject_TestMethod10()
        {
            var obj = (SimpleObject)ObjectInstanceCreator.Create(typeof(SimpleObject).FullName, "[12,12,{\"Height\":999,\"Female\":true}]", null, null);
            Assert.AreEqual(true, obj != null);
            Assert.AreEqual(true, obj.Inner != null);
            Assert.AreEqual(true, obj.Age == 12);
            Assert.AreEqual(true, obj.Name == "sss");
            Assert.AreEqual(true, obj.Inner.Height == 999);
            Assert.AreEqual(true, obj.Inner.Female.Value == true);
        }

        [TestMethod]
        public void SimpleObject_Generic_TestMethod1()
        {
            var inner = (InnerOb_Generic<string>)ObjectInstanceCreator.Create(typeof(InnerOb_Generic<>).FullName, "", new Type[] { typeof(string) }, null);
            var obj = (SimpleObject_Generic<string>)ObjectInstanceCreator.Create(typeof(SimpleObject_Generic<>).FullName,
                "[12]",
                new Type[] { typeof(string) },
                new object[] { inner });
            Assert.AreEqual(true, obj != null);
            Assert.AreEqual(true, obj.Inner != null);
            Assert.AreEqual(true, obj.Age == 12);
            Assert.AreEqual(true, obj.Name == null);
            Assert.AreEqual(true, obj.Inner.Height == 0);
            Assert.AreEqual(true, obj.Inner.Female == null);
        }

        [TestMethod]
        public void SimpleObject_Generic_TestMethod2()
        {
            var inner = (InnerOb_Generic<string>)ObjectInstanceCreator.Create(typeof(InnerOb_Generic<>).FullName, "", new Type[] { typeof(string) }, null);
            var obj = (SimpleObject_Generic<string>)ObjectInstanceCreator.Create(typeof(SimpleObject_Generic<>).FullName,
                "[12]",
                new Type[] { typeof(string) },
                new object[] { inner });
            Assert.AreEqual(true, obj != null);
            Assert.AreEqual(true, obj.Inner != null);
            Assert.AreEqual(true, obj.Age == 12);
            Assert.AreEqual(true, obj.Name == null);
            Assert.AreEqual(true, obj.Inner.Height == 0);
            Assert.AreEqual(true, obj.Inner.Female == null);
        }

        [TestMethod]
        public void SimpleObject_Generic_TestMethod3()
        {
            var inner = (InnerOb_Generic<string>)ObjectInstanceCreator.Create(typeof(InnerOb_Generic<>).FullName, "", new Type[] { typeof(string) }, null);
            var obj = (SimpleObject_Generic<string>)ObjectInstanceCreator.Create(typeof(SimpleObject_Generic<>).FullName,
                "[12,\"me\"]",
                new Type[] { typeof(string) },
                new object[] { inner });
            Assert.AreEqual(true, obj != null);
            Assert.AreEqual(true, obj.Inner != null);
            Assert.AreEqual(true, obj.Age == 12);
            Assert.AreEqual(true, obj.Name == "me");
            Assert.AreEqual(true, obj.Inner.Height == 0);
            Assert.AreEqual(true, obj.Inner.Female == null);
        }

        [TestMethod]
        public void SimpleObject_Generic_TestMethod4()
        {
            var inner = (InnerOb_Generic<string>)ObjectInstanceCreator.Create(typeof(InnerOb_Generic<>).FullName, "", new Type[] { typeof(string) }, null);
            var obj = (SimpleObject_Generic<string>)ObjectInstanceCreator.Create(typeof(SimpleObject_Generic<>).FullName,
                "[\"me\",12]",
                new Type[] { typeof(string) },
                new object[] { inner });
            Assert.AreEqual(true, obj != null);
            Assert.AreEqual(true, obj.Inner != null);
            Assert.AreEqual(true, obj.Age == 12);
            Assert.AreEqual(true, obj.Name == "me");
            Assert.AreEqual(true, obj.Inner.Height == 0);
            Assert.AreEqual(true, obj.Inner.Female == null);
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void SimpleObject_Generic_TestMethod5()
        {
            var inner = (InnerOb_Generic<string>)ObjectInstanceCreator.Create(typeof(InnerOb_Generic<>).FullName, "", new Type[] { typeof(string) }, null);
            var obj = (SimpleObject_Generic<string>)ObjectInstanceCreator.Create(typeof(SimpleObject_Generic<>).FullName,
                "[12,12]",
                new Type[] { typeof(string) },
                new object[] { inner });
            Assert.AreEqual(true, obj != null);
            Assert.AreEqual(true, obj.Inner != null);
            Assert.AreEqual(true, obj.Age == 12);
            Assert.AreEqual(true, obj.Name == "me");
            Assert.AreEqual(true, obj.Inner.Height == 0);
            Assert.AreEqual(true, obj.Inner.Female == null);
        }

        
    }
}